@uniformdev/next-app-router 20.84.0 → 20.86.0

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.
@@ -4479,6 +4479,7 @@ var bton = (base64) => {
4479
4479
  }
4480
4480
  return sign ? -number : number;
4481
4481
  };
4482
+ var isZeroCookieScore = (score) => Math.abs(score) < 1;
4482
4483
  var ssr = typeof document === "undefined";
4483
4484
  var UNIFORM_DEFAULT_COOKIE_NAME = "ufvd";
4484
4485
  var UNIFORM_DEFAULT_QUIRK_COOKIE_NAME = `ufvdqk`;
@@ -4486,6 +4487,7 @@ var _cookieName;
4486
4487
  var _quirkCookieName;
4487
4488
  var _cookieAttributes;
4488
4489
  var _quirksEnabled;
4490
+ var _maxBytes;
4489
4491
  var CookieTransitionDataStore = class extends TransitionDataStore {
4490
4492
  constructor({
4491
4493
  serverCookieValue,
@@ -4493,7 +4495,9 @@ var CookieTransitionDataStore = class extends TransitionDataStore {
4493
4495
  quirkCookieValue,
4494
4496
  quirkCookieName = UNIFORM_DEFAULT_QUIRK_COOKIE_NAME,
4495
4497
  cookieName = UNIFORM_DEFAULT_COOKIE_NAME,
4496
- cookieAttributes = { sameSite: "lax" }
4498
+ cookieAttributes = { sameSite: "lax" },
4499
+ maxBytes,
4500
+ onLogMessage
4497
4501
  }) {
4498
4502
  super({
4499
4503
  initialData: ssr ? parseScoreCookie(serverCookieValue, experimental_quirksEnabled ? quirkCookieValue : void 0) : void 0
@@ -4502,10 +4506,20 @@ var CookieTransitionDataStore = class extends TransitionDataStore {
4502
4506
  __privateAdd4(this, _quirkCookieName);
4503
4507
  __privateAdd4(this, _cookieAttributes);
4504
4508
  __privateAdd4(this, _quirksEnabled);
4509
+ __privateAdd4(this, _maxBytes);
4510
+ __publicField3(this, "onLogMessage");
4505
4511
  __privateSet2(this, _cookieName, cookieName);
4506
4512
  __privateSet2(this, _cookieAttributes, cookieAttributes);
4507
4513
  __privateSet2(this, _quirkCookieName, quirkCookieName);
4508
4514
  __privateSet2(this, _quirksEnabled, experimental_quirksEnabled || false);
4515
+ __privateSet2(this, _maxBytes, maxBytes);
4516
+ this.onLogMessage = onLogMessage;
4517
+ const minimumBytes = minimumCookieBytes(cookieName);
4518
+ if (maxBytes !== void 0 && maxBytes < minimumBytes) {
4519
+ throw new Error(
4520
+ `maxBytes of ${maxBytes} is below the ${minimumBytes} bytes the "${cookieName}" cookie costs when it carries nothing but control group membership, so no visitor could ever meet it.`
4521
+ );
4522
+ }
4509
4523
  }
4510
4524
  handleDelete() {
4511
4525
  if (ssr) return Promise.resolve();
@@ -4515,7 +4529,15 @@ var CookieTransitionDataStore = class extends TransitionDataStore {
4515
4529
  async handleUpdateData(_, computedValue) {
4516
4530
  if (ssr) return;
4517
4531
  if (computedValue.consent) {
4518
- api.set(__privateGet4(this, _cookieName), serializeCookie(computedValue), __privateGet4(this, _cookieAttributes));
4532
+ const cookieValue = serializeCookie(computedValue, {
4533
+ maxBytes: __privateGet4(this, _maxBytes),
4534
+ cookieName: __privateGet4(this, _cookieName),
4535
+ onBudgetExceeded: (dropped, bytes, maxBytes) => {
4536
+ var _a;
4537
+ return (_a = this.onLogMessage) == null ? void 0 : _a.call(this, ["info", 151, { dropped, bytes, maxBytes }]);
4538
+ }
4539
+ });
4540
+ api.set(__privateGet4(this, _cookieName), cookieValue, __privateGet4(this, _cookieAttributes));
4519
4541
  if (__privateGet4(this, _quirksEnabled) && Object.keys(computedValue.quirks || {}).length) {
4520
4542
  const quirkCookieValue = serializeQuirks(computedValue.quirks || {});
4521
4543
  api.set(__privateGet4(this, _quirkCookieName), quirkCookieValue, __privateGet4(this, _cookieAttributes));
@@ -4532,6 +4554,7 @@ _cookieName = /* @__PURE__ */ new WeakMap();
4532
4554
  _quirkCookieName = /* @__PURE__ */ new WeakMap();
4533
4555
  _cookieAttributes = /* @__PURE__ */ new WeakMap();
4534
4556
  _quirksEnabled = /* @__PURE__ */ new WeakMap();
4557
+ _maxBytes = /* @__PURE__ */ new WeakMap();
4535
4558
  var TYPE_SEP = "~";
4536
4559
  var PAIR_SEP = "!";
4537
4560
  var KV_SEP = "-";
@@ -4603,18 +4626,66 @@ function decodeCookieType(type) {
4603
4626
  return acc;
4604
4627
  }, {});
4605
4628
  }
4606
- function serializeCookie(data) {
4629
+ function serializeCookie(data, options = {}) {
4630
+ const { maxBytes, cookieName = UNIFORM_DEFAULT_COOKIE_NAME, onBudgetExceeded } = options;
4631
+ const parts = {
4632
+ tests: { ...data.tests },
4633
+ sessionScores: encodeCookieType(data.sessionScores),
4634
+ scores: encodeCookieType(data.scores),
4635
+ controlGroup: data.controlGroup ? "1" : "0",
4636
+ personalizeVariants: encodePersonalizeVariants(data.personalizeVariants)
4637
+ };
4638
+ let value = serializeCookieParts(parts);
4639
+ if (maxBytes === void 0) {
4640
+ return value;
4641
+ }
4642
+ const overhead = encodeCookieName(cookieName).length + 1;
4643
+ const measure = () => overhead + api.converter.write(value, cookieName).length;
4644
+ if (measure() <= maxBytes) {
4645
+ return value;
4646
+ }
4647
+ const candidates = dropCandidates(parts, data);
4648
+ const dropped = [];
4649
+ for (let i = 0; i < candidates.length && measure() > maxBytes; i++) {
4650
+ const { bucket, key } = candidates[i];
4651
+ delete parts[bucket][key];
4652
+ dropped.push(`${bucket}.${key}`);
4653
+ value = serializeCookieParts(parts);
4654
+ }
4655
+ if (dropped.length) {
4656
+ onBudgetExceeded == null ? void 0 : onBudgetExceeded(dropped, measure(), maxBytes);
4657
+ }
4658
+ return value;
4659
+ }
4660
+ function serializeCookieParts(parts) {
4607
4661
  return [
4608
- serializeCookieType(data.tests),
4609
- serializeCookieType(encodeCookieType(data.sessionScores)),
4610
- serializeCookieType(encodeCookieType(data.scores)),
4611
- data.controlGroup ? "1" : "0",
4612
- serializePersonalizeVariants(data)
4662
+ serializeCookieType(parts.tests),
4663
+ serializeCookieType(parts.sessionScores),
4664
+ serializeCookieType(parts.scores),
4665
+ parts.controlGroup,
4666
+ serializeCookieType(parts.personalizeVariants)
4613
4667
  ].join(TYPE_SEP);
4614
4668
  }
4615
- function serializePersonalizeVariants({
4616
- personalizeVariants
4617
- }) {
4669
+ function dropCandidates(parts, data) {
4670
+ const dimensions = ["sessionScores", "scores"].flatMap(
4671
+ (bucket, order) => Object.keys(parts[bucket]).map((key) => {
4672
+ var _a;
4673
+ return { bucket, key, order, score: (_a = data[bucket][key]) != null ? _a : 0 };
4674
+ })
4675
+ );
4676
+ dimensions.sort(
4677
+ (a, b) => Number(isZeroCookieScore(b.score)) - Number(isZeroCookieScore(a.score)) || a.score - b.score || a.order - b.order || (a.key < b.key ? -1 : 1)
4678
+ );
4679
+ const keysOf = (bucket) => Object.keys(parts[bucket]).sort().map((key) => ({ bucket, key }));
4680
+ return [...dimensions, ...keysOf("personalizeVariants"), ...keysOf("tests")];
4681
+ }
4682
+ function minimumCookieBytes(cookieName) {
4683
+ return encodeCookieName(cookieName).length + 6;
4684
+ }
4685
+ function encodeCookieName(name) {
4686
+ return encodeURIComponent(name).replace(/%(2[346B]|5E|60|7C)/g, decodeURIComponent).replace(/\(/g, "%28").replace(/\)/g, "%29");
4687
+ }
4688
+ function encodePersonalizeVariants(personalizeVariants) {
4618
4689
  const data = {};
4619
4690
  if (typeof personalizeVariants === "object") {
4620
4691
  Object.keys(personalizeVariants).forEach((personalizationName) => {
@@ -4626,8 +4697,7 @@ function serializePersonalizeVariants({
4626
4697
  data[personalizationName] = results.join(",");
4627
4698
  });
4628
4699
  }
4629
- const serialized = serializeCookieType(data);
4630
- return serialized;
4700
+ return data;
4631
4701
  }
4632
4702
  function decodePersonalizeVariants(data) {
4633
4703
  const parsed = parseCookieType(data);
@@ -4674,6 +4744,7 @@ fetchData_fn = async function() {
4674
4744
  this.signalAsyncDataUpdate(serviceData);
4675
4745
  }
4676
4746
  };
4747
+ var isSystemDimension = (dimension) => dimension.startsWith("$");
4677
4748
  var emptyVisitorData = () => ({
4678
4749
  quirks: {},
4679
4750
  scores: {},
@@ -4809,6 +4880,9 @@ var replaceData_fn;
4809
4880
  var setVisitTimeout_fn;
4810
4881
  var isExpired_fn;
4811
4882
  var handleCaps_fn;
4883
+ var pruningManifest_get;
4884
+ var handlePruning_fn;
4885
+ var pruneScores_fn;
4812
4886
  var defaultData_fn;
4813
4887
  var VisitorDataStore = class {
4814
4888
  constructor(options) {
@@ -4919,6 +4993,7 @@ replaceData_fn = function(data, quiet = false) {
4919
4993
  sessionScores: data.sessionScores,
4920
4994
  onLogMessage: __privateGet4(this, _options).onLogMessage
4921
4995
  });
4996
+ __privateMethod(this, _VisitorDataStore_instances, handlePruning_fn).call(this, data);
4922
4997
  const haveScoresChanged = !dequal(oldData == null ? void 0 : oldData.visitorData.scores, data.scores);
4923
4998
  const haveSessionScoresChanged = !dequal(oldData == null ? void 0 : oldData.visitorData.sessionScores, data.sessionScores);
4924
4999
  const haveQuirksChanged = !dequal(oldData == null ? void 0 : oldData.visitorData.quirks, data.quirks);
@@ -4991,6 +5066,48 @@ handleCaps_fn = function(scores) {
4991
5066
  }
4992
5067
  }
4993
5068
  };
5069
+ pruningManifest_get = function() {
5070
+ var _a, _b, _c, _d, _e;
5071
+ const project = (_b = (_a = __privateGet4(this, _options).manifest) == null ? void 0 : _a.data) == null ? void 0 : _b.project;
5072
+ const populated = [(_c = project == null ? void 0 : project.pz) == null ? void 0 : _c.sig, (_d = project == null ? void 0 : project.pz) == null ? void 0 : _d.enr, (_e = project == null ? void 0 : project.pz) == null ? void 0 : _e.agg, project == null ? void 0 : project.test].some(
5073
+ (definitions) => definitions && Object.keys(definitions).length > 0
5074
+ );
5075
+ return populated ? __privateGet4(this, _options).manifest : void 0;
5076
+ };
5077
+ handlePruning_fn = function(data) {
5078
+ var _a, _b;
5079
+ const { pruneUnknownTests, pruneUnknownDimensions } = __privateGet4(this, _options);
5080
+ const manifest = pruneUnknownTests || pruneUnknownDimensions ? __privateGet4(this, _VisitorDataStore_instances, pruningManifest_get) : void 0;
5081
+ const pruned = [];
5082
+ if (pruneUnknownTests && manifest) {
5083
+ for (const test in data.tests) {
5084
+ if (!manifest.getTest(test)) {
5085
+ delete data.tests[test];
5086
+ pruned.push(`tests.${test}`);
5087
+ }
5088
+ }
5089
+ }
5090
+ __privateMethod(this, _VisitorDataStore_instances, pruneScores_fn).call(this, data.scores, "scores", pruned, manifest);
5091
+ __privateMethod(this, _VisitorDataStore_instances, pruneScores_fn).call(this, data.sessionScores, "sessionScores", pruned, manifest);
5092
+ if (pruned.length) {
5093
+ (_b = (_a = __privateGet4(this, _options)).onLogMessage) == null ? void 0 : _b.call(_a, ["info", 150, pruned]);
5094
+ }
5095
+ };
5096
+ pruneScores_fn = function(scores, bucket, pruned, manifest) {
5097
+ const { pruneUnknownDimensions, pruneZeroScores } = __privateGet4(this, _options);
5098
+ if (!pruneUnknownDimensions && !pruneZeroScores) {
5099
+ return;
5100
+ }
5101
+ const pruneUnknown = pruneUnknownDimensions && manifest;
5102
+ for (const dim in scores) {
5103
+ const isUnknown = pruneUnknown && !isSystemDimension(dim) && !manifest.getDimensionByKey(dim);
5104
+ const isZero = pruneZeroScores && (pruneZeroScores === "round" ? isZeroCookieScore(scores[dim]) : scores[dim] === 0);
5105
+ if (isUnknown || isZero) {
5106
+ delete scores[dim];
5107
+ pruned.push(`${bucket}.${dim}`);
5108
+ }
5109
+ }
5110
+ };
4994
5111
  defaultData_fn = function() {
4995
5112
  var _a, _b, _c;
4996
5113
  return {
@@ -1,6 +1,6 @@
1
1
  import { RouteGetResponseEdgehancedComposition } from '@uniformdev/canvas';
2
2
  import { PageState } from '@uniformdev/next-app-router-shared';
3
- import { D as DataClient } from './client-BElN_CWD.js';
3
+ import { D as DataClient } from './client-CCXGmvoG.js';
4
4
 
5
5
  type ResolvedRouteResult = {
6
6
  pageState: PageState;
@@ -1,6 +1,6 @@
1
1
  import { RouteGetResponseEdgehancedComposition } from '@uniformdev/canvas';
2
2
  import { PageState } from '@uniformdev/next-app-router-shared';
3
- import { D as DataClient } from './client-BElN_CWD.mjs';
3
+ import { D as DataClient } from './client-CCXGmvoG.mjs';
4
4
 
5
5
  type ResolvedRouteResult = {
6
6
  pageState: PageState;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@uniformdev/next-app-router",
3
- "version": "20.84.0",
3
+ "version": "20.86.0",
4
4
  "license": "SEE LICENSE IN LICENSE.txt",
5
5
  "scripts": {
6
6
  "build": "tsup",
@@ -100,12 +100,12 @@
100
100
  "vitest": "4.1.11"
101
101
  },
102
102
  "dependencies": {
103
- "@uniformdev/canvas-react": "20.84.0",
104
- "@uniformdev/next-app-router-client": "20.84.0",
105
- "@uniformdev/next-app-router-shared": "20.84.0",
106
- "@uniformdev/redirect": "20.84.0",
107
- "@uniformdev/richtext": "20.84.0",
108
- "@uniformdev/webhooks": "20.84.0",
103
+ "@uniformdev/canvas-react": "20.86.0",
104
+ "@uniformdev/next-app-router-client": "20.86.0",
105
+ "@uniformdev/next-app-router-shared": "20.86.0",
106
+ "@uniformdev/redirect": "20.86.0",
107
+ "@uniformdev/richtext": "20.86.0",
108
+ "@uniformdev/webhooks": "20.86.0",
109
109
  "@vercel/functions": "^3.7.2",
110
110
  "encoding": "^0.1.13",
111
111
  "server-only": "^0.0.1",
@@ -122,5 +122,5 @@
122
122
  "publishConfig": {
123
123
  "access": "public"
124
124
  },
125
- "gitHead": "aed567f635f70f4ba169010c0a1bcaebfe23d0f9"
125
+ "gitHead": "f0e4c0eb0eac24eb1e38a5bd536832f0261b003b"
126
126
  }