@blotout/qinto-cli 0.1.8 → 0.1.9
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 +2307 -1749
- package/dist/index.js.map +1 -1
- package/dist/worker-artifact/app-runtime/index.js +334 -37
- package/dist/worker-artifact/main/9026260a7a674b710223f296c5d2e7a01930cfed-q.js.txt +1 -0
- package/dist/worker-artifact/main/index.js +444 -48
- package/dist/worker-artifact/version.json +6 -6
- package/package.json +1 -1
- package/templates/app/full/ui/src/pages/index.astro +0 -2
- package/templates/ui/src/pages/index.astro +1 -2
- package/dist/worker-artifact/main/9dcfd236748459af038da772477100c4bb0223b7-q.js.txt +0 -1
|
@@ -3036,10 +3036,10 @@ var $ZodObject = /* @__PURE__ */ $constructor("$ZodObject", (inst, def) => {
|
|
|
3036
3036
|
const shape = def.shape;
|
|
3037
3037
|
const propValues = {};
|
|
3038
3038
|
for (const key in shape) {
|
|
3039
|
-
const
|
|
3040
|
-
if (
|
|
3039
|
+
const field2 = shape[key]._zod;
|
|
3040
|
+
if (field2.values) {
|
|
3041
3041
|
propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
|
|
3042
|
-
for (const v of
|
|
3042
|
+
for (const v of field2.values)
|
|
3043
3043
|
propValues[key].add(v);
|
|
3044
3044
|
}
|
|
3045
3045
|
}
|
|
@@ -14741,12 +14741,21 @@ var ENDPOINT_CONTEXT_HEADER = "x-qinto-endpoint-context";
|
|
|
14741
14741
|
var ENDPOINT_OUTCOMES_HEADER = "x-qinto-endpoint-outcomes";
|
|
14742
14742
|
var MAX_ENDPOINT_BODY_BYTES = 1024 * 1024;
|
|
14743
14743
|
var MAX_ENDPOINT_OUTCOMES_BYTES = 64 * 1024;
|
|
14744
|
+
var MAX_ENDPOINT_PATH_LENGTH = 16 * 1024;
|
|
14744
14745
|
var installSchema3 = 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();
|
|
14745
14746
|
var endpointContextSchema = external_exports.object({
|
|
14746
|
-
path
|
|
14747
|
+
// The declared template, which keys the bundle's handler map; `path` is what the caller asked
|
|
14748
|
+
// for. Only `route` may key the rate limiter — a concrete path gives every parameter value its
|
|
14749
|
+
// own bucket, which is no limit at all.
|
|
14750
|
+
route: external_exports.string().min(1).max(255),
|
|
14751
|
+
path: external_exports.string().min(1).max(MAX_ENDPOINT_PATH_LENGTH),
|
|
14752
|
+
// A name is cut from `route`, so the route's own cap bounds it; anything tighter would reject a
|
|
14753
|
+
// parameter the manifest grammar accepts and the worker already matched.
|
|
14754
|
+
params: external_exports.record(external_exports.string().min(1).max(255), external_exports.string().max(MAX_ENDPOINT_PATH_LENGTH)).default({}),
|
|
14747
14755
|
method: external_exports.enum(["GET", "POST", "PUT", "PATCH", "DELETE"]),
|
|
14748
14756
|
mode: external_exports.enum(["webhook", "api"]),
|
|
14749
14757
|
version: external_exports.string().min(1).max(32),
|
|
14758
|
+
site: external_exports.object({ origin: external_exports.string().min(1).max(255) }).strict(),
|
|
14750
14759
|
installs: external_exports.array(installSchema3).min(1).max(15)
|
|
14751
14760
|
}).strict().refine((context) => {
|
|
14752
14761
|
return context.mode === "webhook" || context.installs.length === 1;
|
|
@@ -14761,6 +14770,96 @@ var endpointOutcomesSchema = external_exports.object({
|
|
|
14761
14770
|
).max(15)
|
|
14762
14771
|
}).strict();
|
|
14763
14772
|
|
|
14773
|
+
// ../../../libs/app-envelope/src/oauth.ts
|
|
14774
|
+
var APP_OAUTH_BINDING_PREFIX = "OAUTH_";
|
|
14775
|
+
var appOauthBindingName = (providerId, ordinal) => {
|
|
14776
|
+
return `${APP_OAUTH_BINDING_PREFIX}${providerId.toUpperCase().replaceAll("-", "_")}_${ordinal}`;
|
|
14777
|
+
};
|
|
14778
|
+
var parseAppOauthBinding = (raw) => {
|
|
14779
|
+
if (raw === void 0 || raw === "") {
|
|
14780
|
+
return null;
|
|
14781
|
+
}
|
|
14782
|
+
let parsed;
|
|
14783
|
+
try {
|
|
14784
|
+
parsed = JSON.parse(raw);
|
|
14785
|
+
} catch {
|
|
14786
|
+
return null;
|
|
14787
|
+
}
|
|
14788
|
+
if (typeof parsed !== "object" || parsed === null) {
|
|
14789
|
+
return null;
|
|
14790
|
+
}
|
|
14791
|
+
const value = parsed;
|
|
14792
|
+
if (value["st"] !== "connected" && value["st"] !== "reconnect_required") {
|
|
14793
|
+
return null;
|
|
14794
|
+
}
|
|
14795
|
+
const expiresAt = value["e"];
|
|
14796
|
+
const token = value["t"];
|
|
14797
|
+
return {
|
|
14798
|
+
...typeof token === "string" && token !== "" ? { t: token } : {},
|
|
14799
|
+
e: typeof expiresAt === "number" ? expiresAt : null,
|
|
14800
|
+
st: value["st"]
|
|
14801
|
+
};
|
|
14802
|
+
};
|
|
14803
|
+
|
|
14804
|
+
// ../../../libs/app-envelope/src/observability.ts
|
|
14805
|
+
var APP_OBSERVABILITY_HEADER = "x-qinto-app-observability";
|
|
14806
|
+
var APP_OBSERVABILITY_VERSION = 1;
|
|
14807
|
+
var MAX_APP_OBSERVABILITY_EVENTS = 20;
|
|
14808
|
+
var MAX_APP_SAVED_ERRORS = 5;
|
|
14809
|
+
var MAX_APP_EVENT_NAME_BYTES = 128;
|
|
14810
|
+
var MAX_APP_ACTION_NAME_BYTES = 256;
|
|
14811
|
+
var MAX_APP_ERROR_DESCRIPTION_BYTES = 2048;
|
|
14812
|
+
var MAX_APP_ERROR_PAYLOAD_BYTES = 4096;
|
|
14813
|
+
var MAX_APP_DATA_POINT_BLOB_BYTES = 16 * 1024;
|
|
14814
|
+
var MAX_APP_OBSERVABILITY_BYTES = 32 * 1024;
|
|
14815
|
+
var APP_OBSERVABILITY_JSON_BUDGET = MAX_APP_OBSERVABILITY_BYTES / 4 * 3;
|
|
14816
|
+
var APP_EVENT_STATUSES = ["success", "error"];
|
|
14817
|
+
var APP_ERROR_CATEGORIES = ["authorization", "configuration", "validation", "rate_limit", "upstream", "internal"];
|
|
14818
|
+
var encoder = new TextEncoder();
|
|
14819
|
+
var decoder = new TextDecoder();
|
|
14820
|
+
var observabilityEventSchema = external_exports.object({ ord: external_exports.number().int().min(1), name: external_exports.string().min(1).max(MAX_APP_EVENT_NAME_BYTES), status: external_exports.enum(APP_EVENT_STATUSES) }).strict();
|
|
14821
|
+
var savedErrorSchema = external_exports.object({
|
|
14822
|
+
ord: external_exports.number().int().min(1),
|
|
14823
|
+
category: external_exports.enum(APP_ERROR_CATEGORIES),
|
|
14824
|
+
action: external_exports.string().min(1).max(MAX_APP_ACTION_NAME_BYTES),
|
|
14825
|
+
description: external_exports.string().min(1).max(MAX_APP_ERROR_DESCRIPTION_BYTES),
|
|
14826
|
+
payload: external_exports.string().max(MAX_APP_ERROR_PAYLOAD_BYTES).optional(),
|
|
14827
|
+
error: external_exports.string().max(MAX_APP_ERROR_PAYLOAD_BYTES).optional()
|
|
14828
|
+
}).strict();
|
|
14829
|
+
var appObservabilityRecordSchema = external_exports.object({
|
|
14830
|
+
v: external_exports.literal(APP_OBSERVABILITY_VERSION),
|
|
14831
|
+
truncated: external_exports.boolean().optional(),
|
|
14832
|
+
events: external_exports.array(observabilityEventSchema).max(MAX_APP_OBSERVABILITY_EVENTS),
|
|
14833
|
+
errors: external_exports.array(savedErrorSchema).max(MAX_APP_SAVED_ERRORS)
|
|
14834
|
+
}).strict();
|
|
14835
|
+
var utf8Length = (value) => {
|
|
14836
|
+
return encoder.encode(value).length;
|
|
14837
|
+
};
|
|
14838
|
+
var truncateUtf8 = (value, maxBytes) => {
|
|
14839
|
+
if (utf8Length(value) <= maxBytes) {
|
|
14840
|
+
return value;
|
|
14841
|
+
}
|
|
14842
|
+
let kept = "";
|
|
14843
|
+
let used = 0;
|
|
14844
|
+
for (const character of value) {
|
|
14845
|
+
const size = utf8Length(character);
|
|
14846
|
+
if (used + size > maxBytes) {
|
|
14847
|
+
break;
|
|
14848
|
+
}
|
|
14849
|
+
kept += character;
|
|
14850
|
+
used += size;
|
|
14851
|
+
}
|
|
14852
|
+
return kept;
|
|
14853
|
+
};
|
|
14854
|
+
var serializeAppObservability = (record2) => {
|
|
14855
|
+
const bytes = encoder.encode(JSON.stringify(record2));
|
|
14856
|
+
let binary = "";
|
|
14857
|
+
for (const byte of bytes) {
|
|
14858
|
+
binary += String.fromCharCode(byte);
|
|
14859
|
+
}
|
|
14860
|
+
return btoa(binary);
|
|
14861
|
+
};
|
|
14862
|
+
|
|
14764
14863
|
// ../../../libs/app-envelope/src/ui.ts
|
|
14765
14864
|
var UI_CONTEXT_HEADER = "x-qinto-ui-context";
|
|
14766
14865
|
var MAX_UI_BODY_BYTES = 1024 * 1024;
|
|
@@ -14806,10 +14905,10 @@ var formatSpansRecord = (record2) => {
|
|
|
14806
14905
|
};
|
|
14807
14906
|
|
|
14808
14907
|
// ../../../libs/tail-trace/src/app-spans.ts
|
|
14809
|
-
var
|
|
14810
|
-
var
|
|
14908
|
+
var encoder2 = new TextEncoder();
|
|
14909
|
+
var decoder2 = new TextDecoder();
|
|
14811
14910
|
var serializeAppSpans = (record2) => {
|
|
14812
|
-
const bytes =
|
|
14911
|
+
const bytes = encoder2.encode(JSON.stringify(record2));
|
|
14813
14912
|
let binary = "";
|
|
14814
14913
|
for (const byte of bytes) {
|
|
14815
14914
|
binary += String.fromCharCode(byte);
|
|
@@ -14818,12 +14917,12 @@ var serializeAppSpans = (record2) => {
|
|
|
14818
14917
|
};
|
|
14819
14918
|
|
|
14820
14919
|
// ../../../libs/tail-trace/src/budget.ts
|
|
14821
|
-
var
|
|
14920
|
+
var encoder3 = new TextEncoder();
|
|
14822
14921
|
var byteLength = (value) => {
|
|
14823
|
-
return
|
|
14922
|
+
return encoder3.encode(JSON.stringify(value)).length;
|
|
14824
14923
|
};
|
|
14825
14924
|
var fitsBudget = (text, max) => {
|
|
14826
|
-
return text.length * 3 <= max ||
|
|
14925
|
+
return text.length * 3 <= max || encoder3.encode(text).length <= max;
|
|
14827
14926
|
};
|
|
14828
14927
|
var MIN_KEEP = 64;
|
|
14829
14928
|
var halveLongestString = (holders) => {
|
|
@@ -15407,6 +15506,162 @@ var buildAppsClient = (env, envelope) => {
|
|
|
15407
15506
|
};
|
|
15408
15507
|
};
|
|
15409
15508
|
|
|
15509
|
+
// src/oauth.ts
|
|
15510
|
+
var EXPIRY_FLOOR_MS = 1e3;
|
|
15511
|
+
var read = (env, id, ord, now) => {
|
|
15512
|
+
const raw = env[appOauthBindingName(id, ord)];
|
|
15513
|
+
const parsed = parseAppOauthBinding(typeof raw === "string" ? raw : void 0);
|
|
15514
|
+
if (parsed === null) {
|
|
15515
|
+
return null;
|
|
15516
|
+
}
|
|
15517
|
+
const expired = parsed.e !== null && parsed.e - now < EXPIRY_FLOOR_MS;
|
|
15518
|
+
return {
|
|
15519
|
+
id,
|
|
15520
|
+
status: parsed.st === "connected" && !expired ? "connected" : "reconnect_required",
|
|
15521
|
+
expiresAt: parsed.e
|
|
15522
|
+
};
|
|
15523
|
+
};
|
|
15524
|
+
var buildOauth = (env, ord, now = Date.now) => {
|
|
15525
|
+
return {
|
|
15526
|
+
token: (id) => {
|
|
15527
|
+
const raw = env[appOauthBindingName(id, ord)];
|
|
15528
|
+
const parsed = parseAppOauthBinding(typeof raw === "string" ? raw : void 0);
|
|
15529
|
+
if (parsed === null) {
|
|
15530
|
+
throw new Error(`not_connected: this install has no ${id} connection`);
|
|
15531
|
+
}
|
|
15532
|
+
const state = read(env, id, ord, now());
|
|
15533
|
+
if (parsed.t === void 0 || state?.status !== "connected") {
|
|
15534
|
+
throw new Error(`reconnect_required: the ${id} connection has ended and a site manager must reconnect it`);
|
|
15535
|
+
}
|
|
15536
|
+
return parsed.t;
|
|
15537
|
+
},
|
|
15538
|
+
connection: (id) => {
|
|
15539
|
+
return read(env, id, ord, now());
|
|
15540
|
+
}
|
|
15541
|
+
};
|
|
15542
|
+
};
|
|
15543
|
+
var oauthTokenValues = (env) => {
|
|
15544
|
+
const values = /* @__PURE__ */ new Set();
|
|
15545
|
+
for (const [name, raw] of Object.entries(env)) {
|
|
15546
|
+
if (!name.startsWith("OAUTH_") || typeof raw !== "string") {
|
|
15547
|
+
continue;
|
|
15548
|
+
}
|
|
15549
|
+
const token = parseAppOauthBinding(raw)?.t;
|
|
15550
|
+
if (token !== void 0 && token !== "") {
|
|
15551
|
+
values.add(token);
|
|
15552
|
+
}
|
|
15553
|
+
}
|
|
15554
|
+
return [...values];
|
|
15555
|
+
};
|
|
15556
|
+
var buildUiOauth = (env, installs, now = Date.now) => {
|
|
15557
|
+
const ordinalOf = (installId) => {
|
|
15558
|
+
return installs.find((install) => install.id === installId)?.ord ?? null;
|
|
15559
|
+
};
|
|
15560
|
+
return {
|
|
15561
|
+
token: (id, options) => {
|
|
15562
|
+
const ord = ordinalOf(options.installId);
|
|
15563
|
+
if (ord === null) {
|
|
15564
|
+
throw new Error(`not_connected: ${options.installId} is not an install of this app`);
|
|
15565
|
+
}
|
|
15566
|
+
return buildOauth(env, ord, now).token(id);
|
|
15567
|
+
},
|
|
15568
|
+
connection: (id, options) => {
|
|
15569
|
+
const ord = ordinalOf(options.installId);
|
|
15570
|
+
return ord === null ? null : buildOauth(env, ord, now).connection(id);
|
|
15571
|
+
}
|
|
15572
|
+
};
|
|
15573
|
+
};
|
|
15574
|
+
|
|
15575
|
+
// src/observability-collector.ts
|
|
15576
|
+
import { AsyncLocalStorage as AsyncLocalStorage2 } from "node:async_hooks";
|
|
15577
|
+
var ENVELOPE_OVERHEAD = 64;
|
|
15578
|
+
var collectors = new AsyncLocalStorage2();
|
|
15579
|
+
var serialized = (value) => {
|
|
15580
|
+
if (value instanceof Error) {
|
|
15581
|
+
const stack = value.stack;
|
|
15582
|
+
return JSON.stringify({ name: value.name, message: value.message, ...stack === void 0 ? {} : { stack } });
|
|
15583
|
+
}
|
|
15584
|
+
let text;
|
|
15585
|
+
try {
|
|
15586
|
+
text = JSON.stringify(value);
|
|
15587
|
+
} catch {
|
|
15588
|
+
return String(value);
|
|
15589
|
+
}
|
|
15590
|
+
return typeof text === "string" ? text : String(value);
|
|
15591
|
+
};
|
|
15592
|
+
var field = (value, redact, maxBytes) => {
|
|
15593
|
+
return truncateUtf8(redact(value), maxBytes);
|
|
15594
|
+
};
|
|
15595
|
+
var optionalField = (value, redact) => {
|
|
15596
|
+
if (value === void 0) {
|
|
15597
|
+
return void 0;
|
|
15598
|
+
}
|
|
15599
|
+
return field(serialized(value), redact, MAX_APP_ERROR_PAYLOAD_BYTES);
|
|
15600
|
+
};
|
|
15601
|
+
var createObservabilityCollector = (redact) => {
|
|
15602
|
+
const events = [];
|
|
15603
|
+
const errors = [];
|
|
15604
|
+
let used = ENVELOPE_OVERHEAD;
|
|
15605
|
+
let truncated = false;
|
|
15606
|
+
const size = (entry) => {
|
|
15607
|
+
return utf8Length(JSON.stringify(entry)) + 1;
|
|
15608
|
+
};
|
|
15609
|
+
return {
|
|
15610
|
+
addEvent: (ord, name, status) => {
|
|
15611
|
+
if (name === "" || !APP_EVENT_STATUSES.includes(status)) {
|
|
15612
|
+
truncated = true;
|
|
15613
|
+
return;
|
|
15614
|
+
}
|
|
15615
|
+
if (events.length >= MAX_APP_OBSERVABILITY_EVENTS) {
|
|
15616
|
+
truncated = true;
|
|
15617
|
+
return;
|
|
15618
|
+
}
|
|
15619
|
+
const entry = { ord, name: field(name, redact, MAX_APP_EVENT_NAME_BYTES), status };
|
|
15620
|
+
used += size(entry);
|
|
15621
|
+
events.push(entry);
|
|
15622
|
+
},
|
|
15623
|
+
addError: (ord, input) => {
|
|
15624
|
+
if (!APP_ERROR_CATEGORIES.includes(input.category) || input.action === "" || input.description === "") {
|
|
15625
|
+
truncated = true;
|
|
15626
|
+
return;
|
|
15627
|
+
}
|
|
15628
|
+
if (errors.length >= MAX_APP_SAVED_ERRORS) {
|
|
15629
|
+
truncated = true;
|
|
15630
|
+
return;
|
|
15631
|
+
}
|
|
15632
|
+
const payload = optionalField(input.payload, redact);
|
|
15633
|
+
const error51 = optionalField(input.error, redact);
|
|
15634
|
+
const entry = {
|
|
15635
|
+
ord,
|
|
15636
|
+
category: input.category,
|
|
15637
|
+
action: field(input.action, redact, MAX_APP_ACTION_NAME_BYTES),
|
|
15638
|
+
description: field(input.description, redact, MAX_APP_ERROR_DESCRIPTION_BYTES),
|
|
15639
|
+
...payload === void 0 ? {} : { payload },
|
|
15640
|
+
...error51 === void 0 ? {} : { error: error51 }
|
|
15641
|
+
};
|
|
15642
|
+
const entrySize = size(entry);
|
|
15643
|
+
if (used + entrySize > APP_OBSERVABILITY_JSON_BUDGET) {
|
|
15644
|
+
truncated = true;
|
|
15645
|
+
return;
|
|
15646
|
+
}
|
|
15647
|
+
used += entrySize;
|
|
15648
|
+
errors.push(entry);
|
|
15649
|
+
},
|
|
15650
|
+
record: () => {
|
|
15651
|
+
if (events.length === 0 && errors.length === 0) {
|
|
15652
|
+
return null;
|
|
15653
|
+
}
|
|
15654
|
+
return { v: APP_OBSERVABILITY_VERSION, ...truncated ? { truncated } : {}, events, errors };
|
|
15655
|
+
}
|
|
15656
|
+
};
|
|
15657
|
+
};
|
|
15658
|
+
var runWithObservability = (collector, run) => {
|
|
15659
|
+
return collectors.run(collector, run);
|
|
15660
|
+
};
|
|
15661
|
+
var currentObservability = () => {
|
|
15662
|
+
return collectors.getStore();
|
|
15663
|
+
};
|
|
15664
|
+
|
|
15410
15665
|
// src/observability.ts
|
|
15411
15666
|
var exceptionAttrs = (error51) => {
|
|
15412
15667
|
const attrs = {
|
|
@@ -15429,7 +15684,7 @@ var consoleText = (error51) => {
|
|
|
15429
15684
|
}
|
|
15430
15685
|
return redactUrlParams(error51 instanceof Error ? error51.stack ?? error51.message : String(error51));
|
|
15431
15686
|
};
|
|
15432
|
-
var buildObservability = () => {
|
|
15687
|
+
var buildObservability = (ord) => {
|
|
15433
15688
|
return {
|
|
15434
15689
|
log: (message, attrs) => {
|
|
15435
15690
|
addSpanEvent(message, attrs === void 0 ? {} : { attrs });
|
|
@@ -15439,6 +15694,21 @@ var buildObservability = () => {
|
|
|
15439
15694
|
addSpanEvent(message, { level: "error", attrs: { ...attrs, ...error51 === void 0 ? {} : exceptionAttrs(error51) } });
|
|
15440
15695
|
console.error(redactUrlParams(message), consoleText(error51), redactAttrs(attrs ?? {}));
|
|
15441
15696
|
},
|
|
15697
|
+
event: (name, status) => {
|
|
15698
|
+
addSpanEvent(name, { attrs: { "app.event.status": status } });
|
|
15699
|
+
if (ord !== null) {
|
|
15700
|
+
currentObservability()?.addEvent(ord, name, status);
|
|
15701
|
+
}
|
|
15702
|
+
},
|
|
15703
|
+
saveError: (input) => {
|
|
15704
|
+
addSpanEvent(input.description, {
|
|
15705
|
+
level: "error",
|
|
15706
|
+
attrs: { "app.error.category": input.category, "app.error.action": input.action }
|
|
15707
|
+
});
|
|
15708
|
+
if (ord !== null) {
|
|
15709
|
+
currentObservability()?.addError(ord, input);
|
|
15710
|
+
}
|
|
15711
|
+
},
|
|
15442
15712
|
span: ((...args) => {
|
|
15443
15713
|
const [name] = args;
|
|
15444
15714
|
const { attrs, run } = spanParts(args);
|
|
@@ -15515,6 +15785,9 @@ var secretValues = (env) => {
|
|
|
15515
15785
|
values.add(value);
|
|
15516
15786
|
}
|
|
15517
15787
|
}
|
|
15788
|
+
for (const value of oauthTokenValues(env)) {
|
|
15789
|
+
values.add(value);
|
|
15790
|
+
}
|
|
15518
15791
|
return [...values];
|
|
15519
15792
|
};
|
|
15520
15793
|
var projectInstallValues = (maps, kinds, ord) => {
|
|
@@ -15591,13 +15864,13 @@ var readOnce = (env, subject) => {
|
|
|
15591
15864
|
};
|
|
15592
15865
|
};
|
|
15593
15866
|
var fetchedContext = (env, subject, collector) => {
|
|
15594
|
-
const
|
|
15867
|
+
const read2 = readOnce(env, () => {
|
|
15595
15868
|
return subject("context.load");
|
|
15596
15869
|
});
|
|
15597
15870
|
return {
|
|
15598
15871
|
private: {
|
|
15599
15872
|
load: async () => {
|
|
15600
|
-
return (await
|
|
15873
|
+
return (await read2()).private;
|
|
15601
15874
|
},
|
|
15602
15875
|
set: (patch) => {
|
|
15603
15876
|
subject("context.set");
|
|
@@ -15606,7 +15879,7 @@ var fetchedContext = (env, subject, collector) => {
|
|
|
15606
15879
|
},
|
|
15607
15880
|
shared: {
|
|
15608
15881
|
load: async () => {
|
|
15609
|
-
return (await
|
|
15882
|
+
return (await read2()).shared;
|
|
15610
15883
|
},
|
|
15611
15884
|
set: (patch) => {
|
|
15612
15885
|
subject("context.set");
|
|
@@ -15616,13 +15889,13 @@ var fetchedContext = (env, subject, collector) => {
|
|
|
15616
15889
|
};
|
|
15617
15890
|
};
|
|
15618
15891
|
var asyncContext = (env, subject) => {
|
|
15619
|
-
const
|
|
15892
|
+
const read2 = readOnce(env, () => {
|
|
15620
15893
|
return subject("context.load");
|
|
15621
15894
|
});
|
|
15622
15895
|
return {
|
|
15623
15896
|
private: {
|
|
15624
15897
|
load: async () => {
|
|
15625
|
-
return (await
|
|
15898
|
+
return (await read2()).private;
|
|
15626
15899
|
},
|
|
15627
15900
|
set: async (patch) => {
|
|
15628
15901
|
assertValidPatch(patch);
|
|
@@ -15634,7 +15907,7 @@ var asyncContext = (env, subject) => {
|
|
|
15634
15907
|
},
|
|
15635
15908
|
shared: {
|
|
15636
15909
|
load: async () => {
|
|
15637
|
-
return (await
|
|
15910
|
+
return (await read2()).shared;
|
|
15638
15911
|
},
|
|
15639
15912
|
set: async (patch) => {
|
|
15640
15913
|
assertValidPatch(patch);
|
|
@@ -15694,12 +15967,13 @@ var buildWorkflowContext = (env, stamp) => {
|
|
|
15694
15967
|
env,
|
|
15695
15968
|
install,
|
|
15696
15969
|
startWorkflow: buildStartWorkflow(stamp),
|
|
15970
|
+
oauth: buildOauth(env, stamp.ord),
|
|
15697
15971
|
variables,
|
|
15698
15972
|
secrets,
|
|
15699
15973
|
appVariables,
|
|
15700
15974
|
appSecrets,
|
|
15701
15975
|
userId: stamp.anonId,
|
|
15702
|
-
observability: buildObservability(),
|
|
15976
|
+
observability: buildObservability(stamp.ord),
|
|
15703
15977
|
context: asyncContext(env, (what) => {
|
|
15704
15978
|
return requireSubject(stamp.anonId, what);
|
|
15705
15979
|
}),
|
|
@@ -15776,6 +16050,7 @@ var buildContext = ({
|
|
|
15776
16050
|
secrets,
|
|
15777
16051
|
appVariables: appScope.appVariables,
|
|
15778
16052
|
appSecrets: appScope.appSecrets,
|
|
16053
|
+
oauth: buildOauth(env, install.ord),
|
|
15779
16054
|
user: envelope.user ?? null,
|
|
15780
16055
|
consent: envelope.consent,
|
|
15781
16056
|
geo: envelope.geo,
|
|
@@ -15830,7 +16105,7 @@ var buildContext = ({
|
|
|
15830
16105
|
}
|
|
15831
16106
|
}
|
|
15832
16107
|
},
|
|
15833
|
-
observability: buildObservability(),
|
|
16108
|
+
observability: buildObservability(install.ord),
|
|
15834
16109
|
apps: buildAppsClient(env, envelope)
|
|
15835
16110
|
};
|
|
15836
16111
|
};
|
|
@@ -15927,11 +16202,12 @@ var dispatchSchedule = async (envelope, bundle, env) => {
|
|
|
15927
16202
|
installLabel: install.label,
|
|
15928
16203
|
anonId: null
|
|
15929
16204
|
}),
|
|
16205
|
+
oauth: buildOauth(env, install.ord),
|
|
15930
16206
|
variables,
|
|
15931
16207
|
secrets,
|
|
15932
16208
|
appVariables: appScope.appVariables,
|
|
15933
16209
|
appSecrets: appScope.appSecrets,
|
|
15934
|
-
observability: buildObservability(),
|
|
16210
|
+
observability: buildObservability(install.ord),
|
|
15935
16211
|
apps: buildAppsClient(env, { depth: 0 }),
|
|
15936
16212
|
query: buildCatalogQuery({ env, ticket: install.catalogQueryTicket, installId: install.id }),
|
|
15937
16213
|
push: async (userId, message) => {
|
|
@@ -15993,7 +16269,7 @@ var lifecycleContext = (env, envelope) => {
|
|
|
15993
16269
|
installLabel: install.label,
|
|
15994
16270
|
anonId: null
|
|
15995
16271
|
}),
|
|
15996
|
-
observability: buildObservability()
|
|
16272
|
+
observability: buildObservability(install.ord)
|
|
15997
16273
|
};
|
|
15998
16274
|
};
|
|
15999
16275
|
var migrationContext = (env, envelope) => {
|
|
@@ -16003,7 +16279,9 @@ var migrationContext = (env, envelope) => {
|
|
|
16003
16279
|
site: envelope.site,
|
|
16004
16280
|
appVariables: appScope.appVariables,
|
|
16005
16281
|
appSecrets: appScope.appSecrets,
|
|
16006
|
-
|
|
16282
|
+
// A migration runs once for the site, not once per install, so it has no install to attribute
|
|
16283
|
+
// an event or a saved error to.
|
|
16284
|
+
observability: buildObservability(null)
|
|
16007
16285
|
};
|
|
16008
16286
|
};
|
|
16009
16287
|
var runStatementMigration = async (env, migration) => {
|
|
@@ -16132,19 +16410,22 @@ var handlerRequest = (request, context, body) => {
|
|
|
16132
16410
|
body: body.byteLength === 0 ? void 0 : body
|
|
16133
16411
|
});
|
|
16134
16412
|
};
|
|
16135
|
-
var buildContext2 = ({ env, maps, kinds, appScope, install }) => {
|
|
16413
|
+
var buildContext2 = ({ env, maps, kinds, appScope, install, site, params }) => {
|
|
16136
16414
|
const { variables, secrets } = projectInstallValues(maps, kinds, install.ord);
|
|
16137
16415
|
return {
|
|
16138
16416
|
env,
|
|
16417
|
+
site,
|
|
16418
|
+
params,
|
|
16139
16419
|
install: { id: install.id, label: install.label },
|
|
16140
16420
|
// An endpoint has no visitor, so a workflow it starts cannot push. `push` below is the
|
|
16141
16421
|
// exception: it names its subject rather than inheriting one.
|
|
16142
16422
|
startWorkflow: buildStartWorkflow({ ord: install.ord, installId: install.id, installLabel: install.label, anonId: null }),
|
|
16423
|
+
oauth: buildOauth(env, install.ord),
|
|
16143
16424
|
variables,
|
|
16144
16425
|
secrets,
|
|
16145
16426
|
appVariables: appScope.appVariables,
|
|
16146
16427
|
appSecrets: appScope.appSecrets,
|
|
16147
|
-
observability: buildObservability(),
|
|
16428
|
+
observability: buildObservability(install.ord),
|
|
16148
16429
|
apps: buildAppsClient(env, { depth: 0 }),
|
|
16149
16430
|
push: async (userId, message) => {
|
|
16150
16431
|
await brokerPush(env, {
|
|
@@ -16207,7 +16488,8 @@ var dispatchEndpoint = async ({ request, env, versions }) => {
|
|
|
16207
16488
|
return Response.json({ error: "unknown version" }, { status: 404 });
|
|
16208
16489
|
}
|
|
16209
16490
|
const bundle = versions[context.version];
|
|
16210
|
-
const
|
|
16491
|
+
const endpoints = bundle?.endpoints;
|
|
16492
|
+
const candidate = endpoints !== void 0 && Object.hasOwn(endpoints, context.route) ? endpoints[context.route] : void 0;
|
|
16211
16493
|
if (typeof candidate !== "function") {
|
|
16212
16494
|
return Response.json({ error: "not_found" }, { status: 404 });
|
|
16213
16495
|
}
|
|
@@ -16218,7 +16500,10 @@ var dispatchEndpoint = async ({ request, env, versions }) => {
|
|
|
16218
16500
|
const appScope = projectAppValues(env, appVariableKinds);
|
|
16219
16501
|
const invoke = async (install) => {
|
|
16220
16502
|
return installSpan(install, () => {
|
|
16221
|
-
return handler(
|
|
16503
|
+
return handler(
|
|
16504
|
+
handlerRequest(request, context, body),
|
|
16505
|
+
buildContext2({ env, maps, kinds: variableKinds, appScope, install, site: context.site, params: context.params })
|
|
16506
|
+
);
|
|
16222
16507
|
});
|
|
16223
16508
|
};
|
|
16224
16509
|
const installs = [...context.installs].sort((left, right) => {
|
|
@@ -16241,29 +16526,38 @@ var appSlug = (context) => {
|
|
|
16241
16526
|
return "app";
|
|
16242
16527
|
}
|
|
16243
16528
|
};
|
|
16244
|
-
var withSpans = (response, record2) => {
|
|
16529
|
+
var withSpans = (response, record2, collector) => {
|
|
16245
16530
|
const headers = new Headers(response.headers);
|
|
16246
16531
|
headers.set(APP_SPANS_HEADER, serializeAppSpans(record2));
|
|
16532
|
+
headers.delete(APP_OBSERVABILITY_HEADER);
|
|
16533
|
+
const observability = collector.record();
|
|
16534
|
+
if (observability !== null) {
|
|
16535
|
+
headers.set(APP_OBSERVABILITY_HEADER, serializeAppObservability(observability));
|
|
16536
|
+
}
|
|
16247
16537
|
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
16248
16538
|
};
|
|
16249
16539
|
var runAppInvocation = async (input, handle) => {
|
|
16250
16540
|
let record2 = { spans: [] };
|
|
16541
|
+
const redact = spanRedactor(input.secrets);
|
|
16542
|
+
const collector = createObservabilityCollector(redact);
|
|
16251
16543
|
try {
|
|
16252
16544
|
const response = await runInvocation(
|
|
16253
16545
|
{
|
|
16254
16546
|
name: appSlug(input.context),
|
|
16255
16547
|
trace: parseTraceContext(input.request.headers.get(TRACE_HEADER)),
|
|
16256
16548
|
budget: APP_SPANS_JSON_BUDGET,
|
|
16257
|
-
redact
|
|
16549
|
+
redact,
|
|
16258
16550
|
emit: (emitted) => {
|
|
16259
16551
|
record2 = emitted;
|
|
16260
16552
|
}
|
|
16261
16553
|
},
|
|
16262
|
-
|
|
16554
|
+
() => {
|
|
16555
|
+
return runWithObservability(collector, handle);
|
|
16556
|
+
}
|
|
16263
16557
|
);
|
|
16264
|
-
return withSpans(response, record2);
|
|
16558
|
+
return withSpans(response, record2, collector);
|
|
16265
16559
|
} catch {
|
|
16266
|
-
return withSpans(input.failure(), record2);
|
|
16560
|
+
return withSpans(input.failure(), record2, collector);
|
|
16267
16561
|
}
|
|
16268
16562
|
};
|
|
16269
16563
|
|
|
@@ -16289,21 +16583,21 @@ var capturedBody = async (open) => {
|
|
|
16289
16583
|
return void 0;
|
|
16290
16584
|
}
|
|
16291
16585
|
const reader = body.getReader();
|
|
16292
|
-
const
|
|
16586
|
+
const decoder3 = new TextDecoder();
|
|
16293
16587
|
const expired = new Promise((resolve) => {
|
|
16294
16588
|
timer = setTimeout(() => resolve(null), READ_BUDGET_MS);
|
|
16295
16589
|
});
|
|
16296
16590
|
let text = "";
|
|
16297
16591
|
for (; ; ) {
|
|
16298
|
-
const
|
|
16299
|
-
if (
|
|
16592
|
+
const read2 = await Promise.race([reader.read(), expired]);
|
|
16593
|
+
if (read2 === null) {
|
|
16300
16594
|
abandon(reader);
|
|
16301
16595
|
return INCOMPLETE;
|
|
16302
16596
|
}
|
|
16303
|
-
if (
|
|
16597
|
+
if (read2.done) {
|
|
16304
16598
|
break;
|
|
16305
16599
|
}
|
|
16306
|
-
text +=
|
|
16600
|
+
text += decoder3.decode(read2.value, { stream: true });
|
|
16307
16601
|
if (text.length > MAX_BODY_CHARS) {
|
|
16308
16602
|
abandon(reader);
|
|
16309
16603
|
return TOO_LARGE;
|
|
@@ -16415,6 +16709,9 @@ var dispatchUi = async ({ request, env, versions }) => {
|
|
|
16415
16709
|
env,
|
|
16416
16710
|
install: { id: context.install.id, label: context.install.label },
|
|
16417
16711
|
installs: projectAllInstallValues(maps, variableKinds, context.installs),
|
|
16712
|
+
// The install is named rather than inherited: one panel serves every install, and reading the
|
|
16713
|
+
// subject install's token while showing another account's UI would be silently wrong.
|
|
16714
|
+
oauth: buildUiOauth(env, context.installs),
|
|
16418
16715
|
settings: buildSettings({ env, ticket: context.writeTicket }),
|
|
16419
16716
|
// The panel's viewer is a portal user, not a visitor, so a workflow it starts carries no subject.
|
|
16420
16717
|
startWorkflow: buildUiStartWorkflow(
|
|
@@ -16426,7 +16723,7 @@ var dispatchUi = async ({ request, env, versions }) => {
|
|
|
16426
16723
|
appVariables,
|
|
16427
16724
|
appSecrets,
|
|
16428
16725
|
viewer: context.viewer,
|
|
16429
|
-
observability: buildObservability(),
|
|
16726
|
+
observability: buildObservability(context.install.ord),
|
|
16430
16727
|
apps: buildAppsClient(env, { depth: 0 })
|
|
16431
16728
|
};
|
|
16432
16729
|
let response;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
(function(){var e=class extends Error{constructor(e){super(e),this.name=`QintoError`}},t=class extends e{constructor(e){super(e),this.name=`QintoTimeoutError`}},n=class extends e{constructor(e){super(e),this.name=`QintoEnvironmentError`}},r=`0123456789ABCDEFGHJKMNPQRSTVWXYZ`,i=e=>{let t=new Uint8Array(e);return globalThis.crypto.getRandomValues(t),t},a=e=>{let t=e,n=``;for(let e=0;e<10;e++)n=r.charAt(t%32)+n,t=Math.floor(t/32);let a=``,o=0,s=0;for(let e of i(10))for(o=o<<8|e,s+=8;s>=5;)s-=5,a+=r.charAt(o>>>s&31);return n+a},o=(e=Date.now())=>`evt_${a(e)}_${e}`,s=(e,t)=>{if(e!==void 0)return e;let n=t?.orderId;return typeof n==`string`&&n!==``?n:o()},c=()=>globalThis.document!==void 0,l=[`necessary`,`functional`,`analytics`,`marketing`,`salesOfData`],u=(e,t,n)=>n===void 0||!l.some(e=>e===n)?!1:n===`necessary`||e!==null&&e.categories[n]===!0&&e.apps[t]!==!1,d=()=>{},f=100,p=1024,m=32*1024,h=(e,t,n,r)=>!r||u(e,t,n),g=e=>Object.values(e.config?.apps??{}).some(e=>e.category!==`necessary`||e.capture!==void 0),ee=(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`))},te=(e,t,n,r)=>r===null?e.slug===t&&(n===void 0||n===e.installId):r.has(e.slug),_=(e,t)=>{console.error(`[Qinto] A handler of app "${e.slug}" (install "${e.installId}") failed.`,t)},v=(e,t,n)=>{for(let r of t)try{let t=r(n);t instanceof Promise&&t.catch(t=>{_(e,t)})}catch(t){_(e,t)}},y=(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(d)},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&&S(e,t)&&v(i,[n],e.sharedContext)}};try{n(a)}catch(e){console.error(`[Qinto] App "${t}" failed to activate install "${r.id}".`,e)}},b=(e,t,n)=>{if(!h(e.consent,t,e.target.config?.apps?.[t]?.category,e.target.config?.consentConfiguration?.enabled===!0))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)y(e,t,i,n)},x=(e,t,n)=>h(n,t,e.target.config?.apps?.[t]?.category,e.target.config?.consentConfiguration?.enabled===!0),S=(e,t)=>x(e,t,e.consent)?e.sharedContextConsent===void 0||x(e,t,e.sharedContextConsent):!1,C=e=>{let{categories:t,apps:n}=e;if(!(typeof t!=`object`||!t||typeof n!=`object`||!n))return{categories:t,apps:n}},w=(e,t)=>{let n=e;n.consent=t,n.sharedContextConsent=void 0;for(let n of e.instances)v(n,n.consentHandlers,t);e.onConsentSettled?.(t);for(let[t,n]of e.apps)b(e,t,n)},T=async e=>{try{w(e,await e.client.getConsent())}catch(e){console.error(`[Qinto] The apps consent read failed.`,e)}},ne=e=>{let t;try{t=JSON.stringify(e)}catch{return}if(!(t===void 0||new TextEncoder().encode(t).length>p))return JSON.parse(t)},re=e=>{let t={};for(let n of e){if(n.settled!==n.total||n.values.length!==1)continue;let e=ne(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<=m&&(t[n.instance.slug]=r)}return Object.keys(t).length===0?void 0:t},E=async(e,t)=>{e.onPageEvent?.(e.consent);let n=[],r=[];for(let i of e.instances){if(!h(e.consent,i.slug,e.target.config?.apps?.[i.slug]?.category,e.target.config?.consentConfiguration?.enabled===!0))continue;if(e.target.config?.apps?.[i.slug]?.eventResults?.includes(t.type)!==!0){v(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,_(i,e);continue}r.push(Promise.resolve(n).then(e=>{a.settled+=1,e!==void 0&&a.values.push(e)},e=>{a.settled+=1,_(i,e)}))}}if(r.length>0){let e=d,t=new Promise(t=>{e=t}),n=setTimeout(e,f);await Promise.race([Promise.all(r),t]),clearTimeout(n)}return re(n)},ie=e=>{let{client:t}=e;return{track:async(n,r,i)=>{let a=s(i?.eventId,r),o=t.actionContext(),c=await E(e,{type:`track`,event:n,eventId:a,properties:r??{}});return await t.submitTrack({event:n,eventId:a,properties:r,context:o,appResults:c}),{eventId:a}},identify:async(n,r)=>{let i=t.actionContext(),a=await E(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?.(),g(e.target)){let t=e;t.consent=null,await T(e)}},getAnonId:t.getAnonId,getConsent:t.getConsent,getSession:t.getSession,close:t.close}},ae=(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=C(e),a=r??n.consent;n.sharedContextConsent=r;for(let e of n.instances)x(n,e.slug,a)&&v(e,e.sharedContextHandlers,n.sharedContext)},push:e=>{let{app:t,install:n,topic:r,scope:a,to:o}=e,s=a===`site`;if(ee(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)te(e,t,n,l)&&h(c.consent,e.slug,c.target.config?.apps?.[e.slug]?.category,c.target.config?.consentConfiguration?.enabled===!0)&&v(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)=>{b(o,e,t),o.consent===null&&o.target.config?.consentConfiguration?.enabled===!0&&o.target.config?.apps?.[e]?.category!==`necessary`&&T(o)};for(let[e,t]of n)b(o,e,t);return e.config?.consentConfiguration?.enabled===!0&&g(e)?await T(o):o.onConsentSettled?.(o.consent),ie(o)}}},oe=`PageView`,D=()=>{},se=e=>{e.config?.autoCapture?.pageLoad===!0&&e.q.push([`track`,[oe],D,D])},O=512,k=1440*60*1e3,A=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Object.fromEntries(Object.entries(t).map(([e,t])=>[e,t.value]))])),j=(e,t)=>`qinto:cap:${encodeURIComponent(e)}:${encodeURIComponent(t)}`,M=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>k?null:{at:n.at,anonId:n.anonId,apps:n.apps}}catch{return null}},N=(e,t)=>{try{window.sessionStorage.setItem(e,JSON.stringify(t))}catch{}},P=e=>{try{window.sessionStorage.removeItem(e)}catch{}},F=e=>{try{return decodeURIComponent(e)}catch{return e}},I=()=>{let e={};for(let t of document.cookie.split(`;`)){let n=t.indexOf(`=`);n>0&&(e[t.slice(0,n).trim()]=F(t.slice(n+1)))}return e},L=(e,t)=>{let n={};for(let r of e.queryParams){let e=t.params.get(r);e!==null&&e.length<=O&&(n[r]={value:e,source:`query`})}for(let r of e.cookies){let e=t.cookies[r];e!==void 0&&e.length<=O&&(n[r]={value:e,source:`cookie`})}return n},R=(e,t)=>{let n={params:new URLSearchParams(window.location.search),cookies:I()},r={};for(let[i,a]of Object.entries(e.config?.apps??{})){if(a.capture===void 0||!u(t,i,a.category))continue;let e=L(a.capture,n);Object.keys(e).length>0&&(r[i]=e)}return r},z=(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},B=(e,t,n,r)=>{let i=j(r,n),a=M(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});N(i,{at:Date.now(),anonId:s,apps:o})},f=null,p=()=>{u+=1,o={},l={},P(i)},m=n=>{if(f=n,!c)return;let r=z(R(e,n),{...o,...l});if(Object.keys(r).length===0)return;let i=u;l={...l,...r},t(A(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}},V=Symbol.for(`qinto.connectGate`),H=()=>{},U=e=>{let t=globalThis,n=(t[V]??Promise.resolve()).then(e);return t[V]=n.then(H,H),n},W=class extends e{constructor(e){super(e),this.name=`QintoProtocolError`}},G=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},K=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}},ce=e=>{let n=new Map,r=e=>{let t=n.get(e);if(t!==void 0)return clearTimeout(t.timer),n.delete(e),t};return{submit:r=>new Promise((i,a)=>{let o={frame:r,sent:e.send(r),resolve:i,reject:a,timer:setTimeout(()=>{n.delete(r.ref),a(new t(`The Qinto request timed out.`))},e.requestTimeoutMs)};n.set(r.ref,o)}),flush:()=>{for(let t of n.values())t.sent||=e.send(t.frame)},deliver:e=>{let t=e.ref===void 0?void 0:r(e.ref);if(t!==void 0){if(e.t===`error`){t.reject(new W(e.message));return}t.resolve(K(e))}},rejectAll:e=>{let t=[...n.values()];n.clear();for(let n of t)clearTimeout(n.timer),n.reject(e)}}},le=e=>new WebSocket(e),ue=500,de=3e4,fe=`session not initialized`,pe=(e,t)=>{let n=Math.min(ue*2**e,de);return Math.round(n/2+n/2*t)},me=(e,t)=>e.t===`appPush`?(t.onAppPush?.(e),!0):e.t===`sharedContext`?(t.onSharedContext?.(e),!0):!1,he=e=>{let t=`${e.destination.replace(/\/+$/,``)}/open`,n=null,r=null,i=0,a=null,o=ce({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 W(`connection closed`))},l=()=>{let u=le(t);n=u,u.onopen=()=>{i=0;let e=a;a=null,o.flush(),e?.resolve()},u.onmessage=t=>{let n=G(t.data);if(n===null){s(new W(`invalid message`));return}me(n,e)||(`anonId`in n&&typeof n.anonId==`string`&&e.onAnonId?.(n.anonId),o.deliver(n),n.t===`error`&&n.message===fe&&u.close())},u.onerror=()=>{s(new W(`connection closed`))},u.onclose=()=>{if(n!==u)return;n=null;let e=a;if(e!==null){a=null,c(),e.reject(new W(`connection closed`));return}o.rejectAll(new W(`connection closed`)),r=setTimeout(()=>{r=null,l()},pe(i,Math.random())),i+=1}};return{connect:()=>new Promise((e,t)=>{a={resolve:e,reject:t},l()}),submit:e=>o.submit(e),close:()=>{c()}}},ge=1e4,_e=()=>{let e=0;return()=>(e+=1,`q${e}`)},ve=(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}},ye=(e,t,n,r)=>{let i=null,a=ve(n,r),o=()=>{let e=document.referrer;return{occurredAt:Date.now(),page:{url:window.location.href,...e===``?{}:{referrer:e}},session:a()}},c=async()=>{let n=await e.submit({t:`getSession`,ref:t()});return i=n.anonId,n};return{actionContext:o,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})},identify:async(n,r)=>{await e.submit({t:`identify`,ref:t(),traits:n,id:r,context:o()})},track:async(n,r,i)=>{let a=s(i?.eventId,r);return await e.submit({t:`track`,ref:t(),event:n,eventId:a,properties:r,context:o()}),{eventId:a}},alias:async n=>{await e.submit({t:`alias`,ref:t(),customId:n})},consent:async n=>{await e.submit({t:`consent`,ref:t(),categories:n.categories,apps:n.apps,context:o()})},getConsent:async()=>await e.submit({t:`getConsent`,ref:t()}),getSession:c,getAnonId:async()=>(i===null&&await c(),i),close:()=>{e.close()}}},be=async e=>{if(!c())throw new n(`You are calling init() in a server environment. Use createClient from @blotout/qinto-sdk-server there.`);let t=he({destination:e.destination,requestTimeoutMs:e.requestTimeoutMs??ge,onError:e.onError,onAppPush:e.onAppPush,onSharedContext:e.onSharedContext,onAnonId:e.onAnonId});await U(()=>t.connect());let r=_e();return{client:ye(t,r,e.destination,e.globalName??`qinto`),submitCapture:async e=>await t.submit({t:`capture`,ref:r(),apps:e})}},xe=[`then`,`ready`,`config`],q=()=>{},Se=(e,t)=>(...n)=>{let r=new Promise((r,i)=>{e.q.push([t,n,r,i])});return r.catch(q),r},J=e=>{let t=e;return t._q=1,t.q=[],new Proxy(t,{get:(e,n)=>typeof n!=`string`||xe.includes(n)||n in t?Reflect.get(t,n):(t[n]=Se(t,n),t[n])})},Ce=()=>{let e=document.currentScript?.dataset.qintoGlobal;return typeof e==`string`&&e!==``?e:`qinto`},we=e=>typeof e==`object`&&!!e&&e._q===1,Y=(e=`qinto`)=>{let t=globalThis;if(e in t){let n=t[e];if(!we(n))return null;let r=Array.isArray(n.q)?n:J(n);return r!==n&&Object.defineProperty(t,e,{value:r,writable:!0,enumerable:!0,configurable:!0}),r}let n=J({});return Object.defineProperty(t,e,{value:n,writable:!0,enumerable:!0,configurable:!0}),n},Te=(t,n)=>async(r,i)=>{let a=Reflect.get(t,r);if(typeof a!=`function`)throw new e(`[Qinto] ${n}.${r} is not a method of this tag.`);return a.apply(t,Array.from(i))},Ee=e=>()=>Promise.reject(e),X=(e,t)=>{let[n,r,i,a]=t;e(n,r).then(i,a)},De=e=>{let t=[];return t.push=(...t)=>{for(let n of t)X(e,n);return 0},t},Oe=(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=De(e);for(let n of t)X(e,n)},o=t().then(e=>{a(Te(e,n))},e=>{throw a(Ee(e)),e});return o.catch(q),i.ready=o,o},Z=Ce(),Q=Y(Z),$=`window.${Z}`;if(Q!==null&&Q.ready===void 0){let e=null,t=ae(Q,{onConsentSettled:t=>{e?.settled(t)},onConsentMutation:()=>{e?.clear()},onPageEvent:t=>{e?.settled(t)}});se(Q),Oe(Q,async()=>{let n=Q.config?.destination;if(typeof n!=`string`||n===``)throw Error(`[Qinto] ${$}.config.destination is missing.`);let r=await be({destination:n,globalName:Z,onAppPush:t.push,onSharedContext:t.sharedContext,onAnonId:t=>{e?.observedAnon(t)}});e=B(Q,r.submitCapture,n,Z);let i=await t.connect(r.client);return e.needsAnon()&&e.observedAnon((await r.client.getSession()).anonId),i},$)}})();
|