@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.
@@ -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 field = shape[key]._zod;
3040
- if (field.values) {
3039
+ const field2 = shape[key]._zod;
3040
+ if (field2.values) {
3041
3041
  propValues[key] ?? (propValues[key] = /* @__PURE__ */ new Set());
3042
- for (const v of field.values)
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: external_exports.string().min(1).max(255),
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 encoder = new TextEncoder();
14810
- var decoder = new TextDecoder();
14908
+ var encoder2 = new TextEncoder();
14909
+ var decoder2 = new TextDecoder();
14811
14910
  var serializeAppSpans = (record2) => {
14812
- const bytes = encoder.encode(JSON.stringify(record2));
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 encoder2 = new TextEncoder();
14920
+ var encoder3 = new TextEncoder();
14822
14921
  var byteLength = (value) => {
14823
- return encoder2.encode(JSON.stringify(value)).length;
14922
+ return encoder3.encode(JSON.stringify(value)).length;
14824
14923
  };
14825
14924
  var fitsBudget = (text, max) => {
14826
- return text.length * 3 <= max || encoder2.encode(text).length <= 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 read = readOnce(env, () => {
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 read()).private;
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 read()).shared;
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 read = readOnce(env, () => {
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 read()).private;
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 read()).shared;
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
- observability: buildObservability()
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 candidate = bundle?.endpoints?.[context.path];
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(handlerRequest(request, context, body), buildContext2({ env, maps, kinds: variableKinds, appScope, install }));
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: spanRedactor(input.secrets),
16549
+ redact,
16258
16550
  emit: (emitted) => {
16259
16551
  record2 = emitted;
16260
16552
  }
16261
16553
  },
16262
- handle
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 decoder2 = new TextDecoder();
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 read = await Promise.race([reader.read(), expired]);
16299
- if (read === null) {
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 (read.done) {
16597
+ if (read2.done) {
16304
16598
  break;
16305
16599
  }
16306
- text += decoder2.decode(read.value, { stream: true });
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},$)}})();