@platforma-open/platforma-open.titeseq-analysis 2.3.1 → 2.5.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.
package/dist/index.js CHANGED
@@ -1,4 +1,23 @@
1
1
  import { r as __toESM, t as __commonJSMin } from "./rolldown-runtime-DC62tzP2.js";
2
+ //#region ../model/dist/fitSettings.js
3
+ /** The read coverage both equations require, at the values each fit used on its own. */
4
+ const READ_COVERAGE_DEFAULTS = {
5
+ minReadsPerConcentration: 3,
6
+ minConcentrationPoints: 5
7
+ };
8
+ /** The settings only `hill_gate_index` reads, at the values the block shipped through 2.4.0. */
9
+ const HILL_GATE_INDEX_DEFAULTS = {
10
+ r2ThresholdGood: .8,
11
+ r2ThresholdFailed: .5,
12
+ nMin: .5,
13
+ nMax: 2,
14
+ hookEffectThresholdBin: .2,
15
+ hookEffectThresholdNoBin: .02,
16
+ hookEffectMinReads: 20
17
+ };
18
+ /** Adams 2016's floor, two thirds of the gate range, to three decimals. */
19
+ const DEFAULT_PLATEAU_FLOOR = .667;
20
+ //#endregion
2
21
  //#region ../model/dist/templateParams.js
3
22
  /**
4
23
  * What a project template carries out of a configured block — the mirror image of
@@ -11,11 +30,23 @@ import { r as __toESM, t as __commonJSMin } from "./rolldown-runtime-DC62tzP2.js
11
30
  function deriveTemplateParams(data) {
12
31
  return {
13
32
  abundanceRef: data.abundanceRef,
33
+ filterRef: data.filterRef,
14
34
  concentrationColumnRef: data.concentrationColumnRef,
15
35
  binColumnRef: data.binColumnRef,
16
36
  antigenColumnRef: data.antigenColumnRef,
17
37
  sortFractionColumnRef: data.sortFractionColumnRef,
38
+ binFluorescenceColumnRef: data.binFluorescenceColumnRef,
18
39
  targetAntigen: data.targetAntigen,
40
+ equation: data.equation,
41
+ plateauFloor: data.plateauFloor,
42
+ r2GateMin: data.r2GateMin,
43
+ kdSeGateMax: data.kdSeGateMax,
44
+ requireAllConcentrations: data.requireAllConcentrations,
45
+ replicateColumnRef: data.replicateColumnRef,
46
+ replicateErrorModel: data.replicateErrorModel,
47
+ replicateFitErrorCutoff: data.replicateFitErrorCutoff,
48
+ replicateR2Floor: data.replicateR2Floor,
49
+ replicateCensoredMajority: data.replicateCensoredMajority,
19
50
  minReadsPerConcentration: data.minReadsPerConcentration,
20
51
  minConcentrationPoints: data.minConcentrationPoints,
21
52
  r2ThresholdGood: data.r2ThresholdGood,
@@ -31,7 +62,7 @@ function deriveTemplateParams(data) {
31
62
  //#endregion
32
63
  //#region ../kind/dist/package.js
33
64
  var name = "@platforma-open/platforma-open.titeseq-analysis.kind";
34
- var version$1 = "1.0.0";
65
+ var version$1 = "1.2.0";
35
66
  //#endregion
36
67
  //#region ../node_modules/.pnpm/@platforma-sdk+block-kind@1.1.0/node_modules/@platforma-sdk/block-kind/dist/params.js
37
68
  /**
@@ -123,14 +154,14 @@ function defineBlockKind(meta) {
123
154
  });
124
155
  }
125
156
  //#endregion
126
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/plugin_handle.js
157
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/plugin_handle.js
127
158
  const PLUGIN_OUTPUT_PREFIX = "plugin-output#";
128
159
  /** Construct the output key for a plugin output in the block outputs map. */
129
160
  function pluginOutputKey(handle, outputKey) {
130
161
  return `${PLUGIN_OUTPUT_PREFIX}${handle}#${outputKey}`;
131
162
  }
132
163
  //#endregion
133
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_storage.js
164
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/block_storage.js
134
165
  /**
135
166
  * Discriminator key for BlockStorage format detection.
136
167
  * This unique hash-based key identifies data as BlockStorage vs legacy formats.
@@ -3947,7 +3978,7 @@ objectType({
3947
3978
  content: stringType()
3948
3979
  });
3949
3980
  //#endregion
3950
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
3981
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
3951
3982
  /**
3952
3983
  * Compose a {@link BlockKindReference} from a kind's `name`/`version`.
3953
3984
  *
@@ -3963,7 +3994,7 @@ objectType({
3963
3994
  to: numberType().min(1)
3964
3995
  });
3965
3996
  //#endregion
3966
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/util.js
3997
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/util.js
3967
3998
  function assertNever(x) {
3968
3999
  throw new Error("Unexpected object: " + x);
3969
4000
  }
@@ -3975,7 +4006,7 @@ function uniqueBy(array, makeId) {
3975
4006
  return [...new Map(array.map((e) => [makeId(e), e])).values()];
3976
4007
  }
3977
4008
  //#endregion
3978
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
4009
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
3979
4010
  /**
3980
4011
  * Type guard function that checks if the given value is a valid DataInfo.
3981
4012
  *
@@ -4164,7 +4195,7 @@ function entriesToDataInfo(dataInfoEntries) {
4164
4195
  }
4165
4196
  }
4166
4197
  //#endregion
4167
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/errors.js
4198
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/errors.js
4168
4199
  var ServiceError = class extends Error {
4169
4200
  name = "ServiceError";
4170
4201
  };
@@ -4188,7 +4219,7 @@ function ensureError(value) {
4188
4219
  return new Error(stringifyValue(value));
4189
4220
  }
4190
4221
  //#endregion
4191
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/json.js
4222
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/json.js
4192
4223
  var import_canonicalize = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
4193
4224
  module.exports = function serialize(object) {
4194
4225
  if (typeof object === "number" && isNaN(object)) throw new Error("NaN is not allowed");
@@ -4221,7 +4252,7 @@ function parseJsonSafely(value, fallback) {
4221
4252
  }
4222
4253
  }
4223
4254
  //#endregion
4224
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4255
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4225
4256
  function readMetadata(metadata, key) {
4226
4257
  return metadata?.[key];
4227
4258
  }
@@ -4549,7 +4580,7 @@ function matchAxisId(query, target) {
4549
4580
  return query.name === target.name && matchDomain$1(query.domain, target.domain) && matchDomain$1(query.contextDomain, target.contextDomain);
4550
4581
  }
4551
4582
  //#endregion
4552
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4583
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4553
4584
  const BOOLEAN_TYPES = /* @__PURE__ */ new Set([
4554
4585
  "numericComparison",
4555
4586
  "stringEquals",
@@ -4654,7 +4685,7 @@ function collectSpecQueryColumns(query) {
4654
4685
  return result;
4655
4686
  }
4656
4687
  //#endregion
4657
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4688
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4658
4689
  function mapPTableDef(def, cb) {
4659
4690
  return {
4660
4691
  ...def,
@@ -4697,7 +4728,7 @@ function mapJoinEntry(entry, cb) {
4697
4728
  }
4698
4729
  }
4699
4730
  //#endregion
4700
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_common.js
4731
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_common.js
4701
4732
  function getPTableColumnId(spec) {
4702
4733
  switch (spec.type) {
4703
4734
  case "axis": return {
@@ -4711,7 +4742,7 @@ function getPTableColumnId(spec) {
4711
4742
  }
4712
4743
  }
4713
4744
  //#endregion
4714
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4745
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4715
4746
  function stringifyColumnFilteredId(key) {
4716
4747
  return canonicalizeJson(createColumnFilteredKey(key));
4717
4748
  }
@@ -4744,7 +4775,7 @@ function applyAxisFilters(spec, axisFilters) {
4744
4775
  };
4745
4776
  }
4746
4777
  //#endregion
4747
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4778
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4748
4779
  function isPObjectId(value) {
4749
4780
  if (typeof value !== "string") return false;
4750
4781
  return isPObjectKey(parseJsonSafely(value));
@@ -4779,6 +4810,10 @@ function isGlobalPObjectKey(value) {
4779
4810
  if (typeof value !== "object" || value === null) return false;
4780
4811
  return "__isRef" in value && "blockId" in value && "name" in value;
4781
4812
  }
4813
+ function isGlobalPObjectId(value) {
4814
+ if (typeof value !== "string") return false;
4815
+ return isGlobalPObjectKey(parseJsonSafely(value));
4816
+ }
4782
4817
  function isPObject(obj) {
4783
4818
  return typeof obj === "object" && obj !== null && "id" in obj && "spec" in obj && "data" in obj;
4784
4819
  }
@@ -4827,7 +4862,7 @@ function extractAllColumns(entry) {
4827
4862
  return [...columns.values()];
4828
4863
  }
4829
4864
  //#endregion
4830
- //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.5/node_modules/@milaboratories/helpers/dist/utils.js
4865
+ //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.6/node_modules/@milaboratories/helpers/dist/utils.js
4831
4866
  function isNil$1(v) {
4832
4867
  return v === null || v === void 0;
4833
4868
  }
@@ -4860,13 +4895,13 @@ function isPlainObject$1(value) {
4860
4895
  return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
4861
4896
  }
4862
4897
  //#endregion
4863
- //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.5/node_modules/@milaboratories/helpers/dist/error.js
4898
+ //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.6/node_modules/@milaboratories/helpers/dist/error.js
4864
4899
  function throwError(v) {
4865
4900
  if (typeof v === "string") throw new Error(v);
4866
4901
  else throw v;
4867
4902
  }
4868
4903
  //#endregion
4869
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4904
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4870
4905
  function isColumnDiscoveredKey(obj) {
4871
4906
  return typeof obj === "object" && obj !== null && "__isDiscovered" in obj;
4872
4907
  }
@@ -4941,7 +4976,7 @@ function isString$1(value) {
4941
4976
  return typeof value === "string";
4942
4977
  }
4943
4978
  //#endregion
4944
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
4979
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
4945
4980
  /**
4946
4981
  * Canonically serializes a column key to a branded string id. Accepts both
4947
4982
  * the new {@link ColumnUniversalKey} and the deprecated {@link UniversalPColumnId}
@@ -5115,7 +5150,7 @@ function extractPObjectId(id) {
5115
5150
  throw new Error(`extractPObjectId: unrecognized column id structure: ${JSON.stringify(id)}`);
5116
5151
  }
5117
5152
  //#endregion
5118
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
5153
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
5119
5154
  function isColumnOverriddenKey(obj) {
5120
5155
  return typeof obj === "object" && obj !== null && "__isOverridden" in obj;
5121
5156
  }
@@ -5237,7 +5272,7 @@ function mergeRecord(a, b) {
5237
5272
  };
5238
5273
  }
5239
5274
  //#endregion
5240
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5275
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5241
5276
  function axisKey(axis) {
5242
5277
  return (0, import_canonicalize.default)(getAxisId(axis));
5243
5278
  }
@@ -5483,7 +5518,7 @@ function isAnchorAxisRef(value) {
5483
5518
  return typeof value === "object" && "anchor" in value;
5484
5519
  }
5485
5520
  //#endregion
5486
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5521
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5487
5522
  /**
5488
5523
  * Determines if an axis ID matches an axis selector.
5489
5524
  *
@@ -5563,8 +5598,53 @@ function legacyColumnSelectorsToPredicate(predicateOrSelectors) {
5563
5598
  if (Array.isArray(predicateOrSelectors)) return (spec) => predicateOrSelectors.some((selector) => isPColumnSpec(spec) && matchPColumn(spec, selector));
5564
5599
  else return (spec) => isPColumnSpec(spec) && matchPColumn(spec, predicateOrSelectors);
5565
5600
  }
5601
+ function matchString(matcher, value) {
5602
+ return matcher.type === "exact" ? value === matcher.value : new RegExp(matcher.value).test(value);
5603
+ }
5604
+ function matchMatcherMap(map, target) {
5605
+ const t = target ?? {};
5606
+ for (const [key, matchers] of Object.entries(map)) {
5607
+ const v = t[key];
5608
+ if (v === void 0) return false;
5609
+ if (!matchers.some((m) => matchString(m, v))) return false;
5610
+ }
5611
+ return true;
5612
+ }
5613
+ function matchMultiAxis(selector, axis) {
5614
+ if (selector.type !== void 0 && !selector.type.includes(axis.type)) return false;
5615
+ if (selector.name !== void 0 && !selector.name.some((m) => matchString(m, axis.name))) return false;
5616
+ if (selector.domain !== void 0 && !matchMatcherMap(selector.domain, axis.domain)) return false;
5617
+ if (selector.contextDomain !== void 0 && !matchMatcherMap(selector.contextDomain, axis.contextDomain)) return false;
5618
+ return true;
5619
+ }
5620
+ /** Match a {@link PColumnSpec} against a {@link MultiColumnSelector}. */
5621
+ function matchMultiColumnSelector(spec, selector) {
5622
+ if (selector.type !== void 0 && !selector.type.includes(spec.valueType)) return false;
5623
+ if (selector.name !== void 0 && !selector.name.some((m) => matchString(m, spec.name))) return false;
5624
+ if (selector.domain !== void 0 && !matchMatcherMap(selector.domain, spec.domain)) return false;
5625
+ if (selector.contextDomain !== void 0 && !matchMatcherMap(selector.contextDomain, spec.contextDomain)) return false;
5626
+ if (selector.annotations !== void 0 && !matchMatcherMap(selector.annotations, spec.annotations)) return false;
5627
+ if (selector.axes !== void 0) {
5628
+ const columnAxes = spec.axesSpec.map(getAxisId);
5629
+ if (selector.partialAxesMatch ?? true) {
5630
+ for (const axisSelector of selector.axes) if (!columnAxes.some((axis) => matchMultiAxis(axisSelector, axis))) return false;
5631
+ } else {
5632
+ if (columnAxes.length !== selector.axes.length) return false;
5633
+ for (let i = 0; i < selector.axes.length; i++) if (!matchMultiAxis(selector.axes[i], columnAxes[i])) return false;
5634
+ }
5635
+ }
5636
+ return true;
5637
+ }
5638
+ /**
5639
+ * Convert a {@link MultiColumnSelector} (or array; selectors OR-ed) to a predicate.
5640
+ * Non-PColumn specs always return false.
5641
+ */
5642
+ function multiColumnSelectorsToPredicate(selectors) {
5643
+ const arr = Array.isArray(selectors) ? selectors : [selectors];
5644
+ return (spec) => isPColumnSpec(spec) && arr.some((sel) => matchMultiColumnSelector(spec, sel));
5645
+ }
5566
5646
  //#endregion
5567
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5647
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5568
5648
  function deriveNativeId(spec) {
5569
5649
  const result = {
5570
5650
  kind: spec.kind,
@@ -5576,7 +5656,7 @@ function deriveNativeId(spec) {
5576
5656
  return (0, import_canonicalize.default)(result);
5577
5657
  }
5578
5658
  //#endregion
5579
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5659
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5580
5660
  var LinkerMap = class LinkerMap {
5581
5661
  /** Graph of linkers connected by axes (single or grouped by parents) */
5582
5662
  data;
@@ -5753,7 +5833,7 @@ var LinkerMap = class LinkerMap {
5753
5833
  }
5754
5834
  };
5755
5835
  //#endregion
5756
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
5836
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
5757
5837
  /**
5758
5838
  * Required PFrames version. Bump this in lockstep with the `@milaboratories/pframes-rs-*`
5759
5839
  * version in `pnpm-workspace.yaml` so blocks built against the new SDK refuse to load on
@@ -5795,12 +5875,21 @@ function withEnrichments(ref, requireEnrichments = true) {
5795
5875
  return rest;
5796
5876
  }
5797
5877
  }
5878
+ function createEnrichmentRef(hit, options = {}) {
5879
+ const { path, qualifications } = options;
5880
+ return {
5881
+ __isEnrichment: "v1",
5882
+ hit,
5883
+ ...path !== void 0 && path.length > 0 ? { path } : {},
5884
+ ...qualifications !== void 0 && qualifications.length > 0 ? { qualifications } : {}
5885
+ };
5886
+ }
5798
5887
  /** Compare two PlRefs and returns true if they are qual */
5799
5888
  function plRefsEqual(ref1, ref2, ignoreEnrichments = false) {
5800
5889
  return ref1.blockId === ref2.blockId && ref1.name === ref2.name && (ignoreEnrichments || ref1.requireEnrichments === ref2.requireEnrichments);
5801
5890
  }
5802
5891
  //#endregion
5803
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
5892
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
5804
5893
  function mapValueInVOE(voe, cb) {
5805
5894
  return voe.ok ? {
5806
5895
  ok: true,
@@ -5808,7 +5897,7 @@ function mapValueInVOE(voe, cb) {
5808
5897
  } : voe;
5809
5898
  }
5810
5899
  //#endregion
5811
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
5900
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
5812
5901
  /** Well-known resource type names used across the platform. */
5813
5902
  const ResourceTypeName = {
5814
5903
  StreamManager: "StreamManager",
@@ -5824,6 +5913,7 @@ const ResourceTypeName = {
5824
5913
  BlobMap: "BlobMap",
5825
5914
  BResolveSingle: "BResolveSingle",
5826
5915
  BResolveSingleNoResult: "BResolveSingleNoResult",
5916
+ BResolveChoice: "BResolveChoice",
5827
5917
  BQueryResult: "BQueryResult",
5828
5918
  TengoTemplate: "TengoTemplate",
5829
5919
  TengoLib: "TengoLib",
@@ -5835,9 +5925,13 @@ const ResourceTypeName = {
5835
5925
  JsonString: "json/string",
5836
5926
  JsonArray: "json/array",
5837
5927
  JsonNumber: "json/number",
5928
+ JsonBool: "json/bool",
5929
+ JsonNull: "json/null",
5930
+ JsonErrorTrace: "json/errorTrace",
5838
5931
  BContextEnd: "BContextEnd",
5839
5932
  FrontendFromUrl: "Frontend/FromUrl",
5840
5933
  FrontendFromFolder: "Frontend/FromFolder",
5934
+ FrontendFromLocalTgz: "Frontend/FromLocalTgz",
5841
5935
  BObjectSpec: "BObjectSpec",
5842
5936
  Blob: "Blob",
5843
5937
  Null: "Null",
@@ -5852,7 +5946,7 @@ const ResourceTypeName = {
5852
5946
  SharedEnvelope: "SharedEnvelope"
5853
5947
  };
5854
5948
  //#endregion
5855
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
5949
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
5856
5950
  const SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;
5857
5951
  const { service, isNodeService, isWasmService, isMainService, getServiceKind, getServiceModelMethods, getServiceUiMethods } = (() => {
5858
5952
  const typeMap = /* @__PURE__ */ new Map();
@@ -5891,7 +5985,7 @@ const { service, isNodeService, isWasmService, isMainService, getServiceKind, ge
5891
5985
  };
5892
5986
  })();
5893
5987
  //#endregion
5894
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
5988
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
5895
5989
  const Services = {
5896
5990
  PFrameSpec: service()({
5897
5991
  type: "wasm",
@@ -5985,7 +6079,7 @@ function resolveRequiredServices(flags) {
5985
6079
  }
5986
6080
  Object.fromEntries(Object.keys(Services).map((key) => [`requires${key}`, true]));
5987
6081
  //#endregion
5988
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
6082
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
5989
6083
  function buildMethodMap(pick) {
5990
6084
  const result = {};
5991
6085
  for (const id of Object.values(Services)) result[id] = [...pick(id)];
@@ -5994,7 +6088,7 @@ function buildMethodMap(pick) {
5994
6088
  buildMethodMap(getServiceUiMethods);
5995
6089
  buildMethodMap(getServiceModelMethods);
5996
6090
  //#endregion
5997
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
6091
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
5998
6092
  /** Resource types that hold column collections — DFS stops here and collects. */
5999
6093
  const COLLECT_TYPES = [ResourceTypeName.PFrame];
6000
6094
  /** Resource types DFS descends through when looking for PFrames. */
@@ -6102,7 +6196,7 @@ function indexPoolBlock(block) {
6102
6196
  return result;
6103
6197
  }
6104
6198
  //#endregion
6105
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
6199
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
6106
6200
  /**
6107
6201
  * Id-index over a set of {@link ColumnEntriesProvider}s. Sole job:
6108
6202
  * {@link PObjectId} → {@link LeafEntry}. Generic over the accessor flavour, so
@@ -6139,7 +6233,7 @@ var ColumnRegistry = class {
6139
6233
  }
6140
6234
  };
6141
6235
  //#endregion
6142
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/dedup.js
6236
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/columns/dedup.js
6143
6237
  /**
6144
6238
  * Two-track dedup over an item stream keyed by `ColumnUniversalId`:
6145
6239
  *
@@ -6180,7 +6274,7 @@ function dedupColumns(items, getId, getSpec) {
6180
6274
  return out;
6181
6275
  }
6182
6276
  //#endregion
6183
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
6277
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
6184
6278
  /**
6185
6279
  * Generic entries provider over a single accessor root. Walks `<root>` once
6186
6280
  * from the supplied `rootPath`, builds an id → {@link LeafEntry} map and
@@ -6237,7 +6331,7 @@ var ResultPoolEntriesProvider = class {
6237
6331
  }
6238
6332
  };
6239
6333
  //#endregion
6240
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6334
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6241
6335
  /**
6242
6336
  * Whether `value` is a reference in the readable spelling.
6243
6337
  *
@@ -6306,7 +6400,7 @@ function expandTemplatePlRef(ref) {
6306
6400
  };
6307
6401
  }
6308
6402
  //#endregion
6309
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6403
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.54.1/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6310
6404
  /**
6311
6405
  * Point every column identifier in a block's params at the blocks of the project being built.
6312
6406
  *
@@ -6366,7 +6460,7 @@ function relocateBlockIds(params, blockIds) {
6366
6460
  return walk(params);
6367
6461
  }
6368
6462
  //#endregion
6369
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_migrations.js
6463
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/block_migrations.js
6370
6464
  /** Create a DataVersioned wrapper with correct shape */
6371
6465
  function makeVersionedData(version, data) {
6372
6466
  return {
@@ -6678,9 +6772,10 @@ var DataModelInitialChain = class extends DataModelMigrationChain {
6678
6772
  if (data !== null && typeof data === "object" && "args" in data) return fn(data);
6679
6773
  return data;
6680
6774
  };
6775
+ const initialVersion = this.versionChain[0];
6681
6776
  const step = {
6682
6777
  fromVersion: DATA_MODEL_LEGACY_VERSION,
6683
- toVersion: this.versionChain[0],
6778
+ toVersion: initialVersion,
6684
6779
  migrate: wrappedFn
6685
6780
  };
6686
6781
  return new DataModelMigrationChainWithRecover({
@@ -6944,7 +7039,7 @@ var DataModel = class DataModel {
6944
7039
  }
6945
7040
  };
6946
7041
  //#endregion
6947
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/internal.js
7042
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/internal.js
6948
7043
  /** Utility code helping to identify whether the code is running in actual UI environment */
6949
7044
  function isInUI() {
6950
7045
  return typeof globalThis.getPlatforma !== "undefined" || typeof globalThis.platforma !== "undefined";
@@ -7014,7 +7109,7 @@ function registerFutureAwait(handle, onResolve) {
7014
7109
  futureResolves.get(handle).push(onResolve);
7015
7110
  }
7016
7111
  //#endregion
7017
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
7112
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
7018
7113
  /**
7019
7114
  * All facade callback names as constants.
7020
7115
  * These are the source of truth - the interface is derived from these.
@@ -7052,7 +7147,7 @@ function registerFacadeCallbacks(callbacks) {
7052
7147
  for (const key of Object.values(BlockStorageFacadeCallbacks)) tryRegisterCallback(key, callbacks[key]);
7053
7148
  }
7054
7149
  //#endregion
7055
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/services/block_services.js
7150
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/services/block_services.js
7056
7151
  /**
7057
7152
  * Services required by all V3 blocks by default.
7058
7153
  * Edit this when a new service should be available to all blocks.
@@ -7068,7 +7163,7 @@ const BLOCK_SERVICE_FLAGS = {
7068
7163
  };
7069
7164
  resolveRequiredServices(BLOCK_SERVICE_FLAGS);
7070
7165
  //#endregion
7071
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/future.js
7166
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/render/future.js
7072
7167
  var FutureRef = class FutureRef {
7073
7168
  handle;
7074
7169
  postProcess;
@@ -7096,7 +7191,7 @@ var FutureRef = class FutureRef {
7096
7191
  }
7097
7192
  };
7098
7193
  //#endregion
7099
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/accessor.js
7194
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/render/accessor.js
7100
7195
  function ifDef(value, cb) {
7101
7196
  return value === void 0 ? void 0 : cb(value);
7102
7197
  }
@@ -7346,11 +7441,11 @@ var TreeNodeAccessor = class TreeNodeAccessor {
7346
7441
  }
7347
7442
  };
7348
7443
  //#endregion
7349
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/internal.js
7444
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/render/internal.js
7350
7445
  const MainAccessorName = "main";
7351
7446
  const StagingAccessorName = "staging";
7352
7447
  //#endregion
7353
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7448
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7354
7449
  function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7355
7450
  const sortedFilters = [...axisFilters].sort((a, b) => b[0] - a[0]);
7356
7451
  const { type } = dataInfoEntries;
@@ -7414,7 +7509,7 @@ function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7414
7509
  }
7415
7510
  }
7416
7511
  //#endregion
7417
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7512
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7418
7513
  /**
7419
7514
  * Structural postfix derivation for linked columns (phase 2 of `deriveDistinctLabels`).
7420
7515
  *
@@ -7586,7 +7681,10 @@ function resolveGroup(entries, indices, format) {
7586
7681
  * linked columns by the difference between their sources.
7587
7682
  */
7588
7683
  function derivePostfixes(entries, format = defaultLinkerFormatter) {
7589
- const postfix = [...entries.reduce((acc, e, idx) => acc.set(e.stem, [...acc.get(e.stem) ?? [], idx]), /* @__PURE__ */ new Map()).values()].reduce((acc, idxs) => {
7684
+ const postfix = [...entries.reduce((acc, e, idx) => {
7685
+ const key = `${e.stem}\u0000${e.marker ?? ""}`;
7686
+ return acc.set(key, [...acc.get(key) ?? [], idx]);
7687
+ }, /* @__PURE__ */ new Map()).values()].reduce((acc, idxs) => {
7590
7688
  if (idxs.length < 2) return acc;
7591
7689
  const resolved = resolveGroup(idxs.map((i) => entries[i]), idxs, format);
7592
7690
  return idxs.reduce((m, i, k) => m.set(i, resolved[k]), acc);
@@ -7597,7 +7695,7 @@ function derivePostfixes(entries, format = defaultLinkerFormatter) {
7597
7695
  });
7598
7696
  }
7599
7697
  //#endregion
7600
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7698
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7601
7699
  const DISTANCE_PENALTY = .001;
7602
7700
  const LABEL_TYPE = "__LABEL__";
7603
7701
  const LABEL_TYPE_FULL = "__LABEL__@1";
@@ -7619,9 +7717,10 @@ function isSyntheticType(t) {
7619
7717
  function deriveDistinctLabels(values, options = {}) {
7620
7718
  const stems = deriveStems(values, options);
7621
7719
  return derivePostfixes(values.map((v, i) => {
7622
- const { spec, linkerPath } = extractEntryParts(v);
7720
+ const { spec, linkerPath, marker } = extractEntryParts(v);
7623
7721
  return {
7624
7722
  stem: stems[i],
7723
+ marker,
7625
7724
  hit: spec,
7626
7725
  linkers: (linkerPath ?? []).map((s) => s.spec)
7627
7726
  };
@@ -7639,6 +7738,7 @@ function deriveStems(values, options) {
7639
7738
  if (labelForced) forcedSet.add(LABEL_TYPE_FULL);
7640
7739
  const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);
7641
7740
  const build = (typeSet, force) => buildLabels(records, typeSet, forceTraceElements, separator, force);
7741
+ const finalize = (minimized, rendered) => repairBareLabels(rendered, minimized, records, stats, forceTraceElements, separator);
7642
7742
  if (mainTypes.length === 0) {
7643
7743
  if (secondaryTypes.length !== 0) throw new Error("Non-empty secondary types list while main types list is empty.");
7644
7744
  return build(/* @__PURE__ */ new Set([LABEL_TYPE_FULL]), true) ?? throwError("Failed to derive labels using native column labels");
@@ -7652,7 +7752,7 @@ function deriveStems(values, options) {
7652
7752
  const candidateResult = build(currentSet, false);
7653
7753
  if (candidateResult !== void 0 && countUniqueLabels(candidateResult) === values.length) {
7654
7754
  const minimized = minimizeTypeSet(currentSet, records, stats, forceTraceElements, forcedSet, separator);
7655
- return repairBareByPresence(build(minimized, false) ?? throwError("Failed to derive unique labels"), minimized, records, stats, forcedSet, forceTraceElements, separator);
7755
+ return finalize(minimized, build(minimized, false) ?? throwError("Failed to derive unique labels"));
7656
7756
  }
7657
7757
  additionalType++;
7658
7758
  if (additionalType >= mainTypes.length) {
@@ -7665,20 +7765,22 @@ function deriveStems(values, options) {
7665
7765
  ...mainTypes,
7666
7766
  ...secondaryTypes
7667
7767
  ]), records, stats, forceTraceElements, forcedSet, separator);
7668
- return repairBareByPresence(build(minimized, true) ?? throwError("Failed to derive unique labels"), minimized, records, stats, forcedSet, forceTraceElements, separator);
7768
+ return finalize(minimized, build(minimized, true) ?? throwError("Failed to derive unique labels"));
7669
7769
  }
7670
7770
  function extractEntryParts(entry) {
7671
7771
  if (!("spec" in entry && typeof entry.spec === "object")) return {
7672
7772
  spec: entry,
7673
7773
  extraTrace: void 0,
7674
7774
  linkerPath: void 0,
7675
- qualifications: void 0
7775
+ qualifications: void 0,
7776
+ marker: void 0
7676
7777
  };
7677
7778
  return {
7678
7779
  spec: entry.spec,
7679
7780
  extraTrace: entry.extraTrace,
7680
7781
  linkerPath: entry.linkerPath,
7681
- qualifications: entry.qualifications
7782
+ qualifications: entry.qualifications,
7783
+ marker: entry.marker
7682
7784
  };
7683
7785
  }
7684
7786
  function formatQualification(q) {
@@ -7830,62 +7932,202 @@ function minimizeTypeSet(typeSet, records, stats, forceTraceElements, forcedSet,
7830
7932
  }
7831
7933
  return result;
7832
7934
  }
7833
- const ABSENT_VALUE = "\0absent";
7834
- /** Whether `fullType`'s rendered value differs across the group (absence counts as a value). */
7835
- function typeDistinguishes(records, group, fullType) {
7836
- const values = /* @__PURE__ */ new Set();
7837
- for (const i of group) {
7838
- const ft = records[i].fullTrace.find((e) => e.fullType === fullType);
7839
- values.add(ft?.label ?? ABSENT_VALUE);
7840
- if (values.size > 1) return true;
7841
- }
7842
- return false;
7843
- }
7844
- /** The highest-importance trace type this row HAS (outside `typeSet`) that sets it apart from its
7845
- * group peers. `undefined` when the row carries nothing distinguishing of its own. */
7846
- function bestDistinguishingType(records, group, row, typeSet, forcedSet, forceTraceElements, stats) {
7847
- return records[row].fullTrace.reduce((best, ft) => {
7848
- if (typeSet.has(ft.fullType) || forcedSet.has(ft.fullType) || forceTraceElements?.has(ft.type)) return best;
7849
- if (!typeDistinguishes(records, group, ft.fullType)) return best;
7850
- const imp = stats.importances.get(ft.fullType) ?? 0;
7851
- return best === void 0 || imp > best.imp ? {
7852
- type: ft.fullType,
7853
- imp
7854
- } : best;
7855
- }, void 0)?.type;
7856
- }
7857
- /**
7858
- * Un-bare columns distinguished only "by absence". After minimization a column can end up with a
7859
- * bare trace zone (only the forced native label) while a peer sharing that same base renders extra
7860
- * tokens — the column reads as unique purely because it LACKS what the peer has. For each such bare
7861
- * column this re-renders JUST that column's label with the highest-importance trace type it actually
7862
- * carries that tells it apart from its peers, so every colliding column is distinguished by a token
7863
- * it HAS rather than by omission.
7864
- *
7865
- * Patches individual labels rather than the shared type set on purpose: the set is global, so adding
7866
- * a type there would also decorate unrelated columns in other groups that happen to carry it. Only
7867
- * bare columns' labels grow (a superset of their previous value), so uniqueness is preserved. Groups
7868
- * are keyed by the base = the label rendered from the forced types alone.
7869
- */
7870
- function repairBareByPresence(labels, minimized, records, stats, forcedSet, forceTraceElements, separator) {
7871
- const base = records.map((r) => renderRecordLabel(r, forcedSet, forceTraceElements, separator));
7872
- const isBare = records.map((r, i) => renderRecordLabel(r, minimized, forceTraceElements, separator) === base[i]);
7873
- const groups = records.reduce((acc, _, i) => acc.set(base[i] ?? "", [...acc.get(base[i] ?? "") ?? [], i]), /* @__PURE__ */ new Map());
7935
+ /**
7936
+ * Repairs labels told apart only by what they lack: in a group with the same shown base, a
7937
+ * member is bare when its shown parts are a strict subset of a peer's. The group is re-labelled
7938
+ * from parts all members carry, or bare members add a hidden part (group-wide when labels stay
7939
+ * unique), whichever keeps the more important distinction; labels stay unique across the list.
7940
+ */
7941
+ function repairBareLabels(labels, minimized, records, stats, forceTraceElements, separator) {
7942
+ const traces = records.map((r) => new Map(r.fullTrace.map((ft) => [ft.fullType, ft.label])));
7943
+ const isQualification = (t) => isSyntheticType(t.split("@")[0]);
7944
+ const depths = records.map((r) => {
7945
+ const steps = r.fullTrace.filter((ft) => ft.fullType !== LABEL_TYPE_FULL && !isQualification(ft.fullType));
7946
+ return new Map(steps.map((ft, idx) => [ft.fullType, steps.length - idx]));
7947
+ });
7948
+ const isForced = (t) => forceTraceElements?.has(t.split("@")[0]) === true;
7949
+ const isDistinctionType = (t) => t !== LABEL_TYPE_FULL && !isQualification(t);
7950
+ const importance = (t) => stats.importances.get(t) ?? 0;
7951
+ const byImportance = (a, b) => importance(b) - importance(a);
7952
+ const render = (i, types) => renderRecordLabel(records[i], types, forceTraceElements, separator);
7953
+ const partKey = (t, l) => `${t}\u0000${l}`;
7954
+ const labelShown = minimized.has(LABEL_TYPE_FULL);
7955
+ const baseTypes = new Set(labelShown ? [LABEL_TYPE_FULL] : []);
7956
+ const qualTypes = [...minimized].filter(isQualification);
7957
+ const groups = /* @__PURE__ */ new Map();
7958
+ records.forEach((_, i) => {
7959
+ const key = render(i, baseTypes) ?? "";
7960
+ const group = groups.get(key);
7961
+ if (group) group.push(i);
7962
+ else groups.set(key, [i]);
7963
+ });
7874
7964
  const patched = [...labels];
7875
- for (const group of groups.values()) {
7876
- if (!group.some((i) => !isBare[i])) continue;
7877
- for (const i of group) {
7878
- if (!isBare[i]) continue;
7879
- const chosen = bestDistinguishingType(records, group, i, minimized, forcedSet, forceTraceElements, stats);
7880
- if (chosen === void 0) continue;
7881
- const withToken = /* @__PURE__ */ new Set([...minimized, chosen]);
7882
- patched[i] = renderRecordLabel(records[i], withToken, forceTraceElements, separator) ?? patched[i];
7883
- }
7965
+ const counts = /* @__PURE__ */ new Map();
7966
+ const addCount = (l, d) => counts.set(l, (counts.get(l) ?? 0) + d);
7967
+ for (const l of patched) addCount(l, 1);
7968
+ const tryApply = (members, next) => {
7969
+ if (new Set(next).size !== members.length) return false;
7970
+ for (const i of members) addCount(patched[i], -1);
7971
+ const clashes = next.some((l) => (counts.get(l) ?? 0) > 0);
7972
+ members.forEach((i, k) => {
7973
+ if (!clashes) patched[i] = next[k];
7974
+ addCount(patched[i], 1);
7975
+ });
7976
+ return !clashes;
7977
+ };
7978
+ for (const [key, group] of groups) {
7979
+ if (group.length < 2) continue;
7980
+ const shown = group.map((i) => [...traces[i]].filter(([t]) => t !== LABEL_TYPE_FULL && (minimized.has(t) || isForced(t))));
7981
+ const partKeys = shown.map((parts) => parts.map(([t, l]) => partKey(t, l)));
7982
+ const sigIndex = /* @__PURE__ */ new Map();
7983
+ const setKeys = [];
7984
+ const setMembers = [];
7985
+ const sigOf = partKeys.map((keys, k) => {
7986
+ const sig = [...keys].sort().join("");
7987
+ let s = sigIndex.get(sig);
7988
+ if (s === void 0) {
7989
+ s = setKeys.length;
7990
+ sigIndex.set(sig, s);
7991
+ setKeys.push(keys);
7992
+ setMembers.push([]);
7993
+ }
7994
+ setMembers[s].push(k);
7995
+ return s;
7996
+ });
7997
+ const setSets = setKeys.map((keys) => new Set(keys));
7998
+ const postings = /* @__PURE__ */ new Map();
7999
+ setKeys.forEach((keys, s) => keys.forEach((p) => {
8000
+ const list = postings.get(p);
8001
+ if (list) list.push(s);
8002
+ else postings.set(p, [s]);
8003
+ }));
8004
+ const withParts = setKeys.map((_, s) => s).filter((s) => setKeys[s].length > 0);
8005
+ const supersetSets = setKeys.map((keys, s) => {
8006
+ if (keys.length === 0) return withParts;
8007
+ const rarest = keys.reduce((a, b) => postings.get(a).length <= postings.get(b).length ? a : b);
8008
+ return postings.get(rarest).filter((t) => t !== s && setSets[t].size > keys.length && keys.every((x) => setSets[t].has(x)));
8009
+ });
8010
+ const bare = group.map((_, k) => supersetSets[sigOf[k]].length > 0);
8011
+ if (!bare.some(Boolean)) continue;
8012
+ const typeCount = /* @__PURE__ */ new Map();
8013
+ for (const i of group) for (const t of traces[i].keys()) typeCount.set(t, (typeCount.get(t) ?? 0) + 1);
8014
+ const isUneven = (t) => (typeCount.get(t) ?? 0) > 0 && typeCount.get(t) < group.length;
8015
+ const unevenMax = Math.max(...[...minimized].filter((t) => isDistinctionType(t) && !isForced(t) && isUneven(t)).map(importance));
8016
+ let sharedLabels;
8017
+ let sharedMax = Number.NEGATIVE_INFINITY;
8018
+ if (labelShown && key !== "") {
8019
+ const shared = [...typeCount].filter(([t, n]) => n === group.length && isDistinctionType(t)).map(([t]) => t).sort(byImportance);
8020
+ const chosen = new Set(baseTypes);
8021
+ const distinctCount = (types) => new Set(group.map((i) => render(i, types) ?? "")).size;
8022
+ let count = distinctCount(chosen);
8023
+ for (const t of shared) {
8024
+ if (count === group.length) break;
8025
+ const next = distinctCount(/* @__PURE__ */ new Set([...chosen, t]));
8026
+ if (next > count) {
8027
+ if (chosen.size === baseTypes.size) sharedMax = importance(t);
8028
+ chosen.add(t);
8029
+ count = next;
8030
+ }
8031
+ }
8032
+ const withTags = /* @__PURE__ */ new Set([...chosen, ...qualTypes]);
8033
+ const complete = group.map((i) => render(i, withTags)).filter((l) => l !== void 0);
8034
+ if (count === group.length && complete.length === group.length && new Set(complete).size === group.length) sharedLabels = complete;
8035
+ }
8036
+ const applyBareFix = () => {
8037
+ const bareMembers = group.filter((_, k) => bare[k]);
8038
+ const oldBare = /* @__PURE__ */ new Map();
8039
+ for (const i of bareMembers) oldBare.set(patched[i], (oldBare.get(patched[i]) ?? 0) + 1);
8040
+ const isFree = (l) => (counts.get(l) ?? 0) - (oldBare.get(l) ?? 0) === 0;
8041
+ const shownTypes = (k) => [
8042
+ ...baseTypes,
8043
+ ...shown[k].map(([t]) => t),
8044
+ ...qualTypes
8045
+ ];
8046
+ const setLabels = /* @__PURE__ */ new Map();
8047
+ const labelsIn = (s) => {
8048
+ let byType = setLabels.get(s);
8049
+ if (byType) return byType;
8050
+ byType = /* @__PURE__ */ new Map();
8051
+ for (const m of setMembers[s]) for (const [t, l] of traces[group[m]]) {
8052
+ const entry = byType.get(t) ?? {
8053
+ labels: /* @__PURE__ */ new Set(),
8054
+ n: 0
8055
+ };
8056
+ entry.labels.add(l);
8057
+ entry.n++;
8058
+ byType.set(t, entry);
8059
+ }
8060
+ setLabels.set(s, byType);
8061
+ return byType;
8062
+ };
8063
+ const someDiffers = (s, u, mine) => {
8064
+ const entry = labelsIn(s).get(u);
8065
+ if (entry === void 0) return mine !== void 0;
8066
+ if (entry.n < setMembers[s].length) return true;
8067
+ return entry.labels.size > 1 || !entry.labels.has(mine ?? "");
8068
+ };
8069
+ const extraDepthsOf = /* @__PURE__ */ new Map();
8070
+ const extraDepths = (s) => {
8071
+ let depthsSet = extraDepthsOf.get(s);
8072
+ if (depthsSet) return depthsSet;
8073
+ depthsSet = new Set(supersetSets[s].flatMap((t) => {
8074
+ const rep = setMembers[t][0];
8075
+ return shown[rep].filter(([u, l]) => !isQualification(u) && !setSets[s].has(partKey(u, l))).map(([u]) => depths[group[rep]].get(u));
8076
+ }));
8077
+ extraDepthsOf.set(s, depthsSet);
8078
+ return depthsSet;
8079
+ };
8080
+ const picks = /* @__PURE__ */ new Map();
8081
+ group.forEach((i, k) => {
8082
+ if (!bare[k]) return;
8083
+ const peers = supersetSets[sigOf[k]];
8084
+ const kindDepths = extraDepths(sigOf[k]);
8085
+ const sameKind = (u) => kindDepths.has(depths[i].get(u)) ? 1 : 0;
8086
+ const candidates = [...traces[i].keys()].filter((u) => !minimized.has(u) && !isForced(u)).filter((u) => peers.some((t) => someDiffers(t, u, traces[i].get(u)))).sort((a, b) => sameKind(b) - sameKind(a) || byImportance(a, b));
8087
+ for (const u of candidates) {
8088
+ const label = render(i, /* @__PURE__ */ new Set([...shownTypes(k), u]));
8089
+ if (label !== void 0 && isFree(label)) {
8090
+ picks.set(i, {
8091
+ type: u,
8092
+ label
8093
+ });
8094
+ break;
8095
+ }
8096
+ }
8097
+ });
8098
+ if (picks.size === 0) return false;
8099
+ if (labelShown && key !== "") {
8100
+ const picked = [...new Set([...picks.values()].map((p) => p.type))];
8101
+ const full = group.map((i, k) => render(i, /* @__PURE__ */ new Set([...shownTypes(k), ...picked]))).filter((l) => l !== void 0);
8102
+ if (full.length === group.length && tryApply(group, full)) return true;
8103
+ }
8104
+ const proposed = new Map([...picks].map(([i, p]) => [i, p.label]));
8105
+ for (let changed = true; changed;) {
8106
+ changed = false;
8107
+ const firstOld = /* @__PURE__ */ new Map();
8108
+ for (const [i, l] of proposed) {
8109
+ const old = firstOld.get(l);
8110
+ if (old === void 0) firstOld.set(l, patched[i]);
8111
+ else if (old !== patched[i]) changed = proposed.delete(i);
8112
+ }
8113
+ const kept = new Set(bareMembers.filter((i) => !proposed.has(i)).map((i) => patched[i]));
8114
+ for (const [i, l] of proposed) if (kept.has(l)) changed = proposed.delete(i);
8115
+ }
8116
+ for (const i of bareMembers) addCount(patched[i], -1);
8117
+ for (const i of bareMembers) {
8118
+ patched[i] = proposed.get(i) ?? patched[i];
8119
+ addCount(patched[i], 1);
8120
+ }
8121
+ return proposed.size > 0;
8122
+ };
8123
+ if (sharedLabels && sharedMax >= unevenMax && tryApply(group, sharedLabels)) continue;
8124
+ if (applyBareFix()) continue;
8125
+ if (sharedLabels && sharedMax < unevenMax) tryApply(group, sharedLabels);
7884
8126
  }
7885
8127
  return patched;
7886
8128
  }
7887
8129
  //#endregion
7888
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/label.js
8130
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/render/util/label.js
7889
8131
  /** @deprecated Use deriveDistinctLabels */
7890
8132
  function deriveLabels(values, getSpec, options = {}) {
7891
8133
  return deriveDistinctLabels(values.map(getSpec), options).map((label, i) => ({
@@ -7894,15 +8136,17 @@ function deriveLabels(values, getSpec, options = {}) {
7894
8136
  }));
7895
8137
  }
7896
8138
  //#endregion
7897
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
7898
- const RT_RESOURCE_MAP = "PColumnData/ResourceMap";
7899
- const RT_RESOURCE_MAP_PARTITIONED = "PColumnData/Partitioned/ResourceMap";
7900
- const RT_JSON_PARTITIONED = "PColumnData/JsonPartitioned";
7901
- const RT_BINARY_PARTITIONED = "PColumnData/BinaryPartitioned";
7902
- const RT_PARQUET_PARTITIONED = "PColumnData/ParquetPartitioned";
7903
- const RT_JSON_SUPER_PARTITIONED = "PColumnData/Partitioned/JsonPartitioned";
7904
- const RT_BINARY_SUPER_PARTITIONED = "PColumnData/Partitioned/BinaryPartitioned";
7905
- const RT_PARQUET_SUPER_PARTITIONED = "PColumnData/Partitioned/ParquetPartitioned";
8139
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
8140
+ const PCD_PREFIX = "PColumnData/";
8141
+ const RT_RESOURCE_MAP = PCD_PREFIX + "ResourceMap";
8142
+ const RT_RESOURCE_MAP_PARTITIONED = PCD_PREFIX + "Partitioned/ResourceMap";
8143
+ const RT_JSON_PARTITIONED = PCD_PREFIX + "JsonPartitioned";
8144
+ const RT_BINARY_PARTITIONED = PCD_PREFIX + "BinaryPartitioned";
8145
+ const RT_PARQUET_PARTITIONED = PCD_PREFIX + "ParquetPartitioned";
8146
+ const PCD_SUP_PREFIX = PCD_PREFIX + "Partitioned/";
8147
+ const RT_JSON_SUPER_PARTITIONED = PCD_SUP_PREFIX + "JsonPartitioned";
8148
+ const RT_BINARY_SUPER_PARTITIONED = PCD_SUP_PREFIX + "BinaryPartitioned";
8149
+ const RT_PARQUET_SUPER_PARTITIONED = PCD_SUP_PREFIX + "ParquetPartitioned";
7906
8150
  const removeIndexSuffix = (keyStr) => {
7907
8151
  if (keyStr.endsWith(".index")) return {
7908
8152
  baseKey: keyStr.substring(0, keyStr.length - 6),
@@ -8188,7 +8432,7 @@ function allPColumnsReady(columns) {
8188
8432
  return columns.every(isPColumnReady);
8189
8433
  }
8190
8434
  //#endregion
8191
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
8435
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
8192
8436
  function isPColumnValues(value) {
8193
8437
  if (!Array.isArray(value)) return false;
8194
8438
  if (value.length === 0) return true;
@@ -8222,9 +8466,10 @@ function splitFiltersToAxisFilter(splitFilters) {
8222
8466
  }
8223
8467
  function fallbackIdDeriver(originalId, axisFilters) {
8224
8468
  if (!axisFilters || axisFilters.length === 0) return originalId;
8469
+ const filtersToCanonicalize = [...axisFilters].sort((a, b) => a[0] - b[0]);
8225
8470
  return (0, import_canonicalize.default)({
8226
8471
  id: originalId,
8227
- axisFilters: [...axisFilters].sort((a, b) => a[0] - b[0])
8472
+ axisFilters: filtersToCanonicalize
8228
8473
  });
8229
8474
  }
8230
8475
  /** Checks if a selector object uses any anchor properties */
@@ -8466,7 +8711,7 @@ var PColumnCollection = class {
8466
8711
  }
8467
8712
  };
8468
8713
  //#endregion
8469
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8714
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8470
8715
  /**
8471
8716
  * Builds a ServiceProxy from a ServiceDispatch.
8472
8717
  * Each service method call is forwarded to dispatch.callServiceMethod.
@@ -8475,7 +8720,7 @@ function createServiceProxy(dispatch) {
8475
8720
  return ((serviceId) => Object.freeze(Object.fromEntries(dispatch.getServiceMethods(serviceId).map((method) => [method, (...args) => dispatch.callServiceMethod(serviceId, method, ...args)]))));
8476
8721
  }
8477
8722
  //#endregion
8478
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/services/get_services.js
8723
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/services/get_services.js
8479
8724
  const cachedServices = /* @__PURE__ */ new WeakMap();
8480
8725
  function getService(name, deps) {
8481
8726
  const ctx = deps?.ctx ?? getCfgRenderCtx();
@@ -8489,7 +8734,7 @@ function getService(name, deps) {
8489
8734
  })();
8490
8735
  }
8491
8736
  //#endregion
8492
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8737
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8493
8738
  function patchInSetFilters(filters) {
8494
8739
  const inSetToOrEqual = (predicate) => {
8495
8740
  if (predicate.operator !== "InSet") return predicate;
@@ -8527,7 +8772,7 @@ function patchInSetFilters(filters) {
8527
8772
  return filters.map((filter) => mapFilter(filter, inSetToOrEqual));
8528
8773
  }
8529
8774
  //#endregion
8530
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/render/api.js
8775
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/render/api.js
8531
8776
  /**
8532
8777
  * Helper function to match domain objects
8533
8778
  * @param query Optional domain to match against
@@ -8578,11 +8823,13 @@ var ResultPool = class {
8578
8823
  let refsWithEnrichments = false;
8579
8824
  if (typeof opts !== "undefined") {
8580
8825
  if (typeof opts === "function") labelOps = opts;
8581
- else if (typeof opts === "object") if ("includeNativeLabel" in opts || "separator" in opts || "addLabelAsSuffix" in opts) labelOps = opts;
8582
- else {
8583
- opts = opts;
8584
- labelOps = opts.label ?? {};
8585
- refsWithEnrichments = opts.refsWithEnrichments ?? false;
8826
+ else if (typeof opts === "object") {
8827
+ if ("includeNativeLabel" in opts || "separator" in opts || "addLabelAsSuffix" in opts) labelOps = opts;
8828
+ else {
8829
+ opts = opts;
8830
+ labelOps = opts.label ?? {};
8831
+ refsWithEnrichments = opts.refsWithEnrichments ?? false;
8832
+ }
8586
8833
  }
8587
8834
  }
8588
8835
  if (typeof labelOps === "object") return deriveLabels(filtered, (o) => o.obj, labelOps ?? {}).map(({ value: { ref }, label }) => ({
@@ -8976,27 +9223,27 @@ var PluginRenderCtx = class extends RenderCtxBase {
8976
9223
  }
8977
9224
  };
8978
9225
  //#endregion
8979
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/plugin_model.js
9226
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/plugin_model.js
8980
9227
  /** Internal plugin↔block handshake. `Symbol.for` (not `Symbol`) so it stays
8981
9228
  * identical across multiple `@platforma-sdk/model` copies in one process. */
8982
9229
  const CREATE_PLUGIN_MODEL = Symbol.for("@platforma-sdk/model:createPluginModel");
8983
9230
  //#endregion
8984
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/version.js
8985
- const PlatformaSDKVersion = "1.84.1";
9231
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/version.js
9232
+ const PlatformaSDKVersion = "1.86.3";
8986
9233
  //#endregion
8987
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/bconfig/types.js
9234
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/bconfig/types.js
8988
9235
  function isConfigLambda(cfgOrFh) {
8989
9236
  return cfgOrFh.__renderLambda === true;
8990
9237
  }
8991
9238
  //#endregion
8992
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
9239
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
8993
9240
  function downgradeCfgOrLambda(data) {
8994
9241
  if (data === void 0) return void 0;
8995
9242
  if (isConfigLambda(data)) return data.handle;
8996
9243
  return data;
8997
9244
  }
8998
9245
  //#endregion
8999
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
9246
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
9000
9247
  /**
9001
9248
  * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().
9002
9249
  *
@@ -9350,7 +9597,7 @@ function deriveTemplateParamsFromStorage(storageJson, deriveTemplateParams) {
9350
9597
  }
9351
9598
  }
9352
9599
  //#endregion
9353
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/block_model.js
9600
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/block_model.js
9354
9601
  /**
9355
9602
  * Merges two feature flag objects with type-aware logic:
9356
9603
  * - `supports*` (boolean): OR — `true` if either side is `true`
@@ -9716,7 +9963,7 @@ var BlockModelV3 = class BlockModelV3 {
9716
9963
  }
9717
9964
  };
9718
9965
  //#endregion
9719
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
9966
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
9720
9967
  /** Create id for column copy with added keys in axes domains */
9721
9968
  const colId = (id, domains, contextDomains) => {
9722
9969
  let wid = id.toString();
@@ -9822,7 +10069,7 @@ function getAdditionalColumnsForColumn(blockAxes, column) {
9822
10069
  })];
9823
10070
  }
9824
10071
  //#endregion
9825
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
10072
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
9826
10073
  /**
9827
10074
  * Replace every column leaf whose id equals `fromId` with `toId`, leaving
9828
10075
  * other column refs (linkers, sub-anchors) intact. Wrapper recipes
@@ -9840,1214 +10087,657 @@ function rebrandLeafId(node, fromId, toId) {
9840
10087
  return mapSpecQueryColumns(node, { column: (id) => id === fromId ? toId : id });
9841
10088
  }
9842
10089
  //#endregion
9843
- //#region ../node_modules/.pnpm/lru-cache@11.2.4/node_modules/lru-cache/dist/esm/index.js
9844
- /**
9845
- * @module LRUCache
9846
- */
9847
- const defaultPerf = typeof performance === "object" && performance && typeof performance.now === "function" ? performance : Date;
9848
- const warned = /* @__PURE__ */ new Set();
9849
- /* c8 ignore start */
9850
- const PROCESS = typeof process === "object" && !!process ? process : {};
9851
- /* c8 ignore start */
9852
- const emitWarning = (msg, type, code, fn) => {
9853
- typeof PROCESS.emitWarning === "function" ? PROCESS.emitWarning(msg, type, code, fn) : console.error(`[${code}] ${type}: ${msg}`);
9854
- };
9855
- let AC = globalThis.AbortController;
9856
- let AS = globalThis.AbortSignal;
9857
- /* c8 ignore start */
9858
- if (typeof AC === "undefined") {
9859
- AS = class AbortSignal {
9860
- onabort;
9861
- _onabort = [];
9862
- reason;
9863
- aborted = false;
9864
- addEventListener(_, fn) {
9865
- this._onabort.push(fn);
9866
- }
9867
- };
9868
- AC = class AbortController {
9869
- constructor() {
9870
- warnACPolyfill();
9871
- }
9872
- signal = new AS();
9873
- abort(reason) {
9874
- if (this.signal.aborted) return;
9875
- this.signal.reason = reason;
9876
- this.signal.aborted = true;
9877
- for (const fn of this.signal._onabort) fn(reason);
9878
- this.signal.onabort?.(reason);
9879
- }
9880
- };
9881
- let printACPolyfillWarning = PROCESS.env?.LRU_CACHE_IGNORE_AC_WARNING !== "1";
9882
- const warnACPolyfill = () => {
9883
- if (!printACPolyfillWarning) return;
9884
- printACPolyfillWarning = false;
9885
- emitWarning("AbortController is not defined. If using lru-cache in node 14, load an AbortController polyfill from the `node-abort-controller` package. A minimal polyfill is provided for use by LRUCache.fetch(), but it should not be relied upon in other contexts (eg, passing it to other APIs that use AbortController/AbortSignal might have undesirable effects). You may disable this with LRU_CACHE_IGNORE_AC_WARNING=1 in the env.", "NO_ABORT_CONTROLLER", "ENOTSUP", warnACPolyfill);
9886
- };
9887
- }
9888
- /* c8 ignore stop */
9889
- const shouldWarn = (code) => !warned.has(code);
9890
- const isPosInt = (n) => n && n === Math.floor(n) && n > 0 && isFinite(n);
9891
- /* c8 ignore start */
9892
- const getUintArray = (max) => !isPosInt(max) ? null : max <= Math.pow(2, 8) ? Uint8Array : max <= Math.pow(2, 16) ? Uint16Array : max <= Math.pow(2, 32) ? Uint32Array : max <= Number.MAX_SAFE_INTEGER ? ZeroArray : null;
9893
- /* c8 ignore stop */
9894
- var ZeroArray = class extends Array {
9895
- constructor(size) {
9896
- super(size);
9897
- this.fill(0);
9898
- }
9899
- };
9900
- var Stack = class Stack {
10090
+ //#region ../node_modules/.pnpm/lru-cache@11.5.3/node_modules/lru-cache/dist/esm/browser/index.min.js
10091
+ var L = { hasSubscribers: !1 };
10092
+ var S = L;
10093
+ var W = L;
10094
+ var M = typeof performance == "object" && performance && typeof performance.now == "function" ? performance : Date;
10095
+ var R = () => S.hasSubscribers || W.hasSubscribers;
10096
+ var j = /* @__PURE__ */ new Set();
10097
+ var I = typeof process == "object" && process ? process : {};
10098
+ var P = (d, e, t, i) => {
10099
+ typeof I.emitWarning == "function" ? I.emitWarning(d, e, t, i) : console.error(`[${t}] ${e}: ${d}`);
10100
+ };
10101
+ var k = (d) => !j.has(d);
10102
+ var T = (d) => !!d && d === Math.floor(d) && d > 0 && isFinite(d);
10103
+ var G = (d) => T(d) ? d <= Math.pow(2, 8) ? Uint8Array : d <= Math.pow(2, 16) ? Uint16Array : d <= Math.pow(2, 32) ? Uint32Array : d <= Number.MAX_SAFE_INTEGER ? O : null : null;
10104
+ var O = class extends Array {
10105
+ constructor(e) {
10106
+ super(e), this.fill(0);
10107
+ }
10108
+ };
10109
+ var x = class d {
9901
10110
  heap;
9902
10111
  length;
9903
- static #constructing = false;
9904
- static create(max) {
9905
- const HeapCls = getUintArray(max);
9906
- if (!HeapCls) return [];
9907
- Stack.#constructing = true;
9908
- const s = new Stack(max, HeapCls);
9909
- Stack.#constructing = false;
9910
- return s;
9911
- }
9912
- constructor(max, HeapCls) {
9913
- /* c8 ignore start */
9914
- if (!Stack.#constructing) throw new TypeError("instantiate Stack using Stack.create(n)");
9915
- /* c8 ignore stop */
9916
- this.heap = new HeapCls(max);
9917
- this.length = 0;
9918
- }
9919
- push(n) {
9920
- this.heap[this.length++] = n;
10112
+ static #o = !1;
10113
+ static create(e) {
10114
+ let t = G(e);
10115
+ if (!t) return [];
10116
+ d.#o = !0;
10117
+ let i = new d(e, t);
10118
+ return d.#o = !1, i;
10119
+ }
10120
+ constructor(e, t) {
10121
+ if (!d.#o) throw new TypeError("instantiate Stack using Stack.create(n)");
10122
+ this.heap = new t(e), this.length = 0;
10123
+ }
10124
+ push(e) {
10125
+ this.heap[this.length++] = e;
9921
10126
  }
9922
10127
  pop() {
9923
10128
  return this.heap[--this.length];
9924
10129
  }
9925
10130
  };
9926
- /**
9927
- * Default export, the thing you're using this module to get.
9928
- *
9929
- * The `K` and `V` types define the key and value types, respectively. The
9930
- * optional `FC` type defines the type of the `context` object passed to
9931
- * `cache.fetch()` and `cache.memo()`.
9932
- *
9933
- * Keys and values **must not** be `null` or `undefined`.
9934
- *
9935
- * All properties from the options object (with the exception of `max`,
9936
- * `maxSize`, `fetchMethod`, `memoMethod`, `dispose` and `disposeAfter`) are
9937
- * added as normal public members. (The listed options are read-only getters.)
9938
- *
9939
- * Changing any of these will alter the defaults for subsequent method calls.
9940
- */
9941
- var LRUCache = class LRUCache {
9942
- #max;
9943
- #maxSize;
9944
- #dispose;
9945
- #onInsert;
9946
- #disposeAfter;
9947
- #fetchMethod;
9948
- #memoMethod;
9949
- #perf;
9950
- /**
9951
- * {@link LRUCache.OptionsBase.perf}
9952
- */
10131
+ var U = class d {
10132
+ #o;
10133
+ #c;
10134
+ #S;
10135
+ #O;
10136
+ #w;
10137
+ #M;
10138
+ #I;
10139
+ #m;
9953
10140
  get perf() {
9954
- return this.#perf;
10141
+ return this.#m;
9955
10142
  }
9956
- /**
9957
- * {@link LRUCache.OptionsBase.ttl}
9958
- */
9959
10143
  ttl;
9960
- /**
9961
- * {@link LRUCache.OptionsBase.ttlResolution}
9962
- */
9963
10144
  ttlResolution;
9964
- /**
9965
- * {@link LRUCache.OptionsBase.ttlAutopurge}
9966
- */
9967
10145
  ttlAutopurge;
9968
- /**
9969
- * {@link LRUCache.OptionsBase.updateAgeOnGet}
9970
- */
9971
10146
  updateAgeOnGet;
9972
- /**
9973
- * {@link LRUCache.OptionsBase.updateAgeOnHas}
9974
- */
9975
10147
  updateAgeOnHas;
9976
- /**
9977
- * {@link LRUCache.OptionsBase.allowStale}
9978
- */
9979
10148
  allowStale;
9980
- /**
9981
- * {@link LRUCache.OptionsBase.noDisposeOnSet}
9982
- */
9983
10149
  noDisposeOnSet;
9984
- /**
9985
- * {@link LRUCache.OptionsBase.noUpdateTTL}
9986
- */
9987
10150
  noUpdateTTL;
9988
- /**
9989
- * {@link LRUCache.OptionsBase.maxEntrySize}
9990
- */
9991
10151
  maxEntrySize;
9992
- /**
9993
- * {@link LRUCache.OptionsBase.sizeCalculation}
9994
- */
9995
10152
  sizeCalculation;
9996
- /**
9997
- * {@link LRUCache.OptionsBase.noDeleteOnFetchRejection}
9998
- */
9999
10153
  noDeleteOnFetchRejection;
10000
- /**
10001
- * {@link LRUCache.OptionsBase.noDeleteOnStaleGet}
10002
- */
10003
10154
  noDeleteOnStaleGet;
10004
- /**
10005
- * {@link LRUCache.OptionsBase.allowStaleOnFetchAbort}
10006
- */
10007
10155
  allowStaleOnFetchAbort;
10008
- /**
10009
- * {@link LRUCache.OptionsBase.allowStaleOnFetchRejection}
10010
- */
10011
10156
  allowStaleOnFetchRejection;
10012
- /**
10013
- * {@link LRUCache.OptionsBase.ignoreFetchAbort}
10014
- */
10015
10157
  ignoreFetchAbort;
10016
- #size;
10017
- #calculatedSize;
10018
- #keyMap;
10019
- #keyList;
10020
- #valList;
10021
- #next;
10022
- #prev;
10023
- #head;
10024
- #tail;
10025
- #free;
10026
- #disposed;
10027
- #sizes;
10028
- #starts;
10029
- #ttls;
10030
- #autopurgeTimers;
10031
- #hasDispose;
10032
- #hasFetchMethod;
10033
- #hasDisposeAfter;
10034
- #hasOnInsert;
10035
- /**
10036
- * Do not call this method unless you need to inspect the
10037
- * inner workings of the cache. If anything returned by this
10038
- * object is modified in any way, strange breakage may occur.
10039
- *
10040
- * These fields are private for a reason!
10041
- *
10042
- * @internal
10043
- */
10044
- static unsafeExposeInternals(c) {
10158
+ backgroundFetchSize;
10159
+ #n;
10160
+ #b;
10161
+ #s;
10162
+ #i;
10163
+ #t;
10164
+ #l;
10165
+ #u;
10166
+ #a;
10167
+ #h;
10168
+ #y;
10169
+ #r;
10170
+ #_;
10171
+ #F;
10172
+ #d;
10173
+ #g;
10174
+ #T;
10175
+ #U;
10176
+ #f;
10177
+ #D;
10178
+ static unsafeExposeInternals(e) {
10045
10179
  return {
10046
- starts: c.#starts,
10047
- ttls: c.#ttls,
10048
- autopurgeTimers: c.#autopurgeTimers,
10049
- sizes: c.#sizes,
10050
- keyMap: c.#keyMap,
10051
- keyList: c.#keyList,
10052
- valList: c.#valList,
10053
- next: c.#next,
10054
- prev: c.#prev,
10180
+ starts: e.#F,
10181
+ ttls: e.#d,
10182
+ autopurgeTimers: e.#g,
10183
+ sizes: e.#_,
10184
+ keyMap: e.#s,
10185
+ keyList: e.#i,
10186
+ valList: e.#t,
10187
+ next: e.#l,
10188
+ prev: e.#u,
10055
10189
  get head() {
10056
- return c.#head;
10190
+ return e.#a;
10057
10191
  },
10058
10192
  get tail() {
10059
- return c.#tail;
10193
+ return e.#h;
10060
10194
  },
10061
- free: c.#free,
10062
- isBackgroundFetch: (p) => c.#isBackgroundFetch(p),
10063
- backgroundFetch: (k, index, options, context) => c.#backgroundFetch(k, index, options, context),
10064
- moveToTail: (index) => c.#moveToTail(index),
10065
- indexes: (options) => c.#indexes(options),
10066
- rindexes: (options) => c.#rindexes(options),
10067
- isStale: (index) => c.#isStale(index)
10195
+ free: e.#y,
10196
+ isBackgroundFetch: (t) => e.#e(t),
10197
+ backgroundFetch: (t, i, s, n) => e.#P(t, i, s, n),
10198
+ moveToTail: (t) => e.#L(t),
10199
+ indexes: (t) => e.#A(t),
10200
+ rindexes: (t) => e.#z(t),
10201
+ isStale: (t) => e.#p(t)
10068
10202
  };
10069
10203
  }
10070
- /**
10071
- * {@link LRUCache.OptionsBase.max} (read-only)
10072
- */
10073
10204
  get max() {
10074
- return this.#max;
10205
+ return this.#o;
10075
10206
  }
10076
- /**
10077
- * {@link LRUCache.OptionsBase.maxSize} (read-only)
10078
- */
10079
10207
  get maxSize() {
10080
- return this.#maxSize;
10208
+ return this.#c;
10081
10209
  }
10082
- /**
10083
- * The total computed size of items in the cache (read-only)
10084
- */
10085
10210
  get calculatedSize() {
10086
- return this.#calculatedSize;
10211
+ return this.#b;
10087
10212
  }
10088
- /**
10089
- * The number of items stored in the cache (read-only)
10090
- */
10091
10213
  get size() {
10092
- return this.#size;
10214
+ return this.#n;
10093
10215
  }
10094
- /**
10095
- * {@link LRUCache.OptionsBase.fetchMethod} (read-only)
10096
- */
10097
10216
  get fetchMethod() {
10098
- return this.#fetchMethod;
10217
+ return this.#M;
10099
10218
  }
10100
10219
  get memoMethod() {
10101
- return this.#memoMethod;
10220
+ return this.#I;
10102
10221
  }
10103
- /**
10104
- * {@link LRUCache.OptionsBase.dispose} (read-only)
10105
- */
10106
10222
  get dispose() {
10107
- return this.#dispose;
10223
+ return this.#S;
10108
10224
  }
10109
- /**
10110
- * {@link LRUCache.OptionsBase.onInsert} (read-only)
10111
- */
10112
10225
  get onInsert() {
10113
- return this.#onInsert;
10226
+ return this.#O;
10114
10227
  }
10115
- /**
10116
- * {@link LRUCache.OptionsBase.disposeAfter} (read-only)
10117
- */
10118
10228
  get disposeAfter() {
10119
- return this.#disposeAfter;
10120
- }
10121
- constructor(options) {
10122
- const { max = 0, ttl, ttlResolution = 1, ttlAutopurge, updateAgeOnGet, updateAgeOnHas, allowStale, dispose, onInsert, disposeAfter, noDisposeOnSet, noUpdateTTL, maxSize = 0, maxEntrySize = 0, sizeCalculation, fetchMethod, memoMethod, noDeleteOnFetchRejection, noDeleteOnStaleGet, allowStaleOnFetchRejection, allowStaleOnFetchAbort, ignoreFetchAbort, perf } = options;
10123
- if (perf !== void 0) {
10124
- if (typeof perf?.now !== "function") throw new TypeError("perf option must have a now() method if specified");
10125
- }
10126
- this.#perf = perf ?? defaultPerf;
10127
- if (max !== 0 && !isPosInt(max)) throw new TypeError("max option must be a nonnegative integer");
10128
- const UintArray = max ? getUintArray(max) : Array;
10129
- if (!UintArray) throw new Error("invalid max value: " + max);
10130
- this.#max = max;
10131
- this.#maxSize = maxSize;
10132
- this.maxEntrySize = maxEntrySize || this.#maxSize;
10133
- this.sizeCalculation = sizeCalculation;
10134
- if (this.sizeCalculation) {
10135
- if (!this.#maxSize && !this.maxEntrySize) throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");
10136
- if (typeof this.sizeCalculation !== "function") throw new TypeError("sizeCalculation set to non-function");
10137
- }
10138
- if (memoMethod !== void 0 && typeof memoMethod !== "function") throw new TypeError("memoMethod must be a function if defined");
10139
- this.#memoMethod = memoMethod;
10140
- if (fetchMethod !== void 0 && typeof fetchMethod !== "function") throw new TypeError("fetchMethod must be a function if specified");
10141
- this.#fetchMethod = fetchMethod;
10142
- this.#hasFetchMethod = !!fetchMethod;
10143
- this.#keyMap = /* @__PURE__ */ new Map();
10144
- this.#keyList = new Array(max).fill(void 0);
10145
- this.#valList = new Array(max).fill(void 0);
10146
- this.#next = new UintArray(max);
10147
- this.#prev = new UintArray(max);
10148
- this.#head = 0;
10149
- this.#tail = 0;
10150
- this.#free = Stack.create(max);
10151
- this.#size = 0;
10152
- this.#calculatedSize = 0;
10153
- if (typeof dispose === "function") this.#dispose = dispose;
10154
- if (typeof onInsert === "function") this.#onInsert = onInsert;
10155
- if (typeof disposeAfter === "function") {
10156
- this.#disposeAfter = disposeAfter;
10157
- this.#disposed = [];
10158
- } else {
10159
- this.#disposeAfter = void 0;
10160
- this.#disposed = void 0;
10161
- }
10162
- this.#hasDispose = !!this.#dispose;
10163
- this.#hasOnInsert = !!this.#onInsert;
10164
- this.#hasDisposeAfter = !!this.#disposeAfter;
10165
- this.noDisposeOnSet = !!noDisposeOnSet;
10166
- this.noUpdateTTL = !!noUpdateTTL;
10167
- this.noDeleteOnFetchRejection = !!noDeleteOnFetchRejection;
10168
- this.allowStaleOnFetchRejection = !!allowStaleOnFetchRejection;
10169
- this.allowStaleOnFetchAbort = !!allowStaleOnFetchAbort;
10170
- this.ignoreFetchAbort = !!ignoreFetchAbort;
10171
- if (this.maxEntrySize !== 0) {
10172
- if (this.#maxSize !== 0) {
10173
- if (!isPosInt(this.#maxSize)) throw new TypeError("maxSize must be a positive integer if specified");
10174
- }
10175
- if (!isPosInt(this.maxEntrySize)) throw new TypeError("maxEntrySize must be a positive integer if specified");
10176
- this.#initializeSizeTracking();
10177
- }
10178
- this.allowStale = !!allowStale;
10179
- this.noDeleteOnStaleGet = !!noDeleteOnStaleGet;
10180
- this.updateAgeOnGet = !!updateAgeOnGet;
10181
- this.updateAgeOnHas = !!updateAgeOnHas;
10182
- this.ttlResolution = isPosInt(ttlResolution) || ttlResolution === 0 ? ttlResolution : 1;
10183
- this.ttlAutopurge = !!ttlAutopurge;
10184
- this.ttl = ttl || 0;
10185
- if (this.ttl) {
10186
- if (!isPosInt(this.ttl)) throw new TypeError("ttl must be a positive integer if specified");
10187
- this.#initializeTTLTracking();
10188
- }
10189
- if (this.#max === 0 && this.ttl === 0 && this.#maxSize === 0) throw new TypeError("At least one of max, maxSize, or ttl is required");
10190
- if (!this.ttlAutopurge && !this.#max && !this.#maxSize) {
10191
- const code = "LRU_CACHE_UNBOUNDED";
10192
- if (shouldWarn(code)) {
10193
- warned.add(code);
10194
- emitWarning("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.", "UnboundedCacheWarning", code, LRUCache);
10195
- }
10196
- }
10197
- }
10198
- /**
10199
- * Return the number of ms left in the item's TTL. If item is not in cache,
10200
- * returns `0`. Returns `Infinity` if item is in cache without a defined TTL.
10201
- */
10202
- getRemainingTTL(key) {
10203
- return this.#keyMap.has(key) ? Infinity : 0;
10204
- }
10205
- #initializeTTLTracking() {
10206
- const ttls = new ZeroArray(this.#max);
10207
- const starts = new ZeroArray(this.#max);
10208
- this.#ttls = ttls;
10209
- this.#starts = starts;
10210
- const purgeTimers = this.ttlAutopurge ? new Array(this.#max) : void 0;
10211
- this.#autopurgeTimers = purgeTimers;
10212
- this.#setItemTTL = (index, ttl, start = this.#perf.now()) => {
10213
- starts[index] = ttl !== 0 ? start : 0;
10214
- ttls[index] = ttl;
10215
- if (purgeTimers?.[index]) {
10216
- clearTimeout(purgeTimers[index]);
10217
- purgeTimers[index] = void 0;
10218
- }
10219
- if (ttl !== 0 && purgeTimers) {
10220
- const t = setTimeout(() => {
10221
- if (this.#isStale(index)) this.#delete(this.#keyList[index], "expire");
10222
- }, ttl + 1);
10223
- /* c8 ignore start */
10224
- if (t.unref) t.unref();
10225
- /* c8 ignore stop */
10226
- purgeTimers[index] = t;
10227
- }
10228
- };
10229
- this.#updateItemAge = (index) => {
10230
- starts[index] = ttls[index] !== 0 ? this.#perf.now() : 0;
10231
- };
10232
- this.#statusTTL = (status, index) => {
10233
- if (ttls[index]) {
10234
- const ttl = ttls[index];
10235
- const start = starts[index];
10236
- /* c8 ignore next */
10237
- if (!ttl || !start) return;
10238
- status.ttl = ttl;
10239
- status.start = start;
10240
- status.now = cachedNow || getNow();
10241
- status.remainingTTL = ttl - (status.now - start);
10242
- }
10243
- };
10244
- let cachedNow = 0;
10245
- const getNow = () => {
10246
- const n = this.#perf.now();
10229
+ return this.#w;
10230
+ }
10231
+ constructor(e) {
10232
+ let { max: t = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: o, updateAgeOnHas: l, allowStale: h, dispose: r, onInsert: c, disposeAfter: m, noDisposeOnSet: _, noUpdateTTL: u, maxSize: g = 0, maxEntrySize: f = 0, sizeCalculation: y, fetchMethod: a, memoMethod: w, noDeleteOnFetchRejection: F, noDeleteOnStaleGet: b, allowStaleOnFetchRejection: p, allowStaleOnFetchAbort: A, ignoreFetchAbort: z, backgroundFetchSize: C = 1, perf: E } = e;
10233
+ if (this.backgroundFetchSize = C, E !== void 0 && typeof E?.now != "function") throw new TypeError("perf option must have a now() method if specified");
10234
+ if (this.#m = E ?? M, t !== 0 && !T(t)) throw new TypeError("max option must be a nonnegative integer");
10235
+ let v = t ? G(t) : Array;
10236
+ if (!v) throw new Error("invalid max value: " + t);
10237
+ if (this.#o = t, this.#c = g, this.maxEntrySize = f || this.#c, this.sizeCalculation = y, this.sizeCalculation) {
10238
+ if (!this.#c && !this.maxEntrySize) throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");
10239
+ if (typeof this.sizeCalculation != "function") throw new TypeError("sizeCalculation set to non-function");
10240
+ }
10241
+ if (w !== void 0 && typeof w != "function") throw new TypeError("memoMethod must be a function if defined");
10242
+ if (this.#I = w, a !== void 0 && typeof a != "function") throw new TypeError("fetchMethod must be a function if specified");
10243
+ if (this.#M = a, this.#U = !!a, this.#s = /* @__PURE__ */ new Map(), this.#i = Array.from({ length: t }).fill(void 0), this.#t = Array.from({ length: t }).fill(void 0), this.#l = new v(t), this.#u = new v(t), this.#a = 0, this.#h = 0, this.#y = x.create(t), this.#n = 0, this.#b = 0, typeof r == "function" && (this.#S = r), typeof c == "function" && (this.#O = c), typeof m == "function" ? (this.#w = m, this.#r = []) : (this.#w = void 0, this.#r = void 0), this.#T = !!this.#S, this.#D = !!this.#O, this.#f = !!this.#w, this.noDisposeOnSet = !!_, this.noUpdateTTL = !!u, this.noDeleteOnFetchRejection = !!F, this.allowStaleOnFetchRejection = !!p, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!z, this.maxEntrySize !== 0) {
10244
+ if (this.#c !== 0 && !T(this.#c)) throw new TypeError("maxSize must be a positive integer if specified");
10245
+ if (!T(this.maxEntrySize)) throw new TypeError("maxEntrySize must be a positive integer if specified");
10246
+ this.#X();
10247
+ }
10248
+ if (this.allowStale = !!h, this.noDeleteOnStaleGet = !!b, this.updateAgeOnGet = !!o, this.updateAgeOnHas = !!l, this.ttlResolution = T(s) || s === 0 ? s : 1, this.ttlAutopurge = !!n, this.ttl = i || 0, this.ttl) {
10249
+ if (!T(this.ttl)) throw new TypeError("ttl must be a positive integer if specified");
10250
+ this.#k();
10251
+ }
10252
+ if (this.#o === 0 && this.ttl === 0 && this.#c === 0) throw new TypeError("At least one of max, maxSize, or ttl is required");
10253
+ if (!this.ttlAutopurge && !this.#o && !this.#c) {
10254
+ let D = "LRU_CACHE_UNBOUNDED";
10255
+ k(D) && (j.add(D), P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.", "UnboundedCacheWarning", D, d));
10256
+ }
10257
+ }
10258
+ getRemainingTTL(e) {
10259
+ return this.#s.has(e) ? 1 / 0 : 0;
10260
+ }
10261
+ #k() {
10262
+ let e = new O(this.#o), t = new O(this.#o);
10263
+ this.#d = e, this.#F = t;
10264
+ let i = this.ttlAutopurge ? Array.from({ length: this.#o }) : void 0;
10265
+ this.#g = i, this.#H = (h, r, c = this.#m.now()) => {
10266
+ t[h] = r !== 0 ? c : 0, e[h] = r, s(h, r);
10267
+ }, this.#R = (h) => {
10268
+ t[h] = e[h] !== 0 ? this.#m.now() : 0, s(h, e[h]);
10269
+ };
10270
+ let s = this.ttlAutopurge ? (h, r) => {
10271
+ if (i?.[h] && (clearTimeout(i[h]), i[h] = void 0), r && r !== 0 && i) {
10272
+ let c = setTimeout(() => {
10273
+ this.#p(h) ? (this.#E(this.#i[h], "expire"), i[h] = void 0) : s(h, l(h));
10274
+ }, r + 1);
10275
+ c.unref && c.unref(), i[h] = c;
10276
+ }
10277
+ } : () => {};
10278
+ this.#v = (h, r) => {
10279
+ if (e[r]) {
10280
+ let c = e[r], m = t[r];
10281
+ if (!c || !m) return;
10282
+ h.ttl = c, h.start = m, h.now = n || o();
10283
+ h.remainingTTL = c - (h.now - m);
10284
+ }
10285
+ };
10286
+ let n = 0, o = () => {
10287
+ let h = this.#m.now();
10247
10288
  if (this.ttlResolution > 0) {
10248
- cachedNow = n;
10249
- const t = setTimeout(() => cachedNow = 0, this.ttlResolution);
10250
- /* c8 ignore start */
10251
- if (t.unref) t.unref();
10252
- }
10253
- return n;
10254
- };
10255
- this.getRemainingTTL = (key) => {
10256
- const index = this.#keyMap.get(key);
10257
- if (index === void 0) return 0;
10258
- const ttl = ttls[index];
10259
- const start = starts[index];
10260
- if (!ttl || !start) return Infinity;
10261
- return ttl - ((cachedNow || getNow()) - start);
10262
- };
10263
- this.#isStale = (index) => {
10264
- const s = starts[index];
10265
- const t = ttls[index];
10266
- return !!t && !!s && (cachedNow || getNow()) - s > t;
10267
- };
10268
- }
10269
- #updateItemAge = () => {};
10270
- #statusTTL = () => {};
10271
- #setItemTTL = () => {};
10272
- /* c8 ignore stop */
10273
- #isStale = () => false;
10274
- #initializeSizeTracking() {
10275
- const sizes = new ZeroArray(this.#max);
10276
- this.#calculatedSize = 0;
10277
- this.#sizes = sizes;
10278
- this.#removeItemSize = (index) => {
10279
- this.#calculatedSize -= sizes[index];
10280
- sizes[index] = 0;
10281
- };
10282
- this.#requireSize = (k, v, size, sizeCalculation) => {
10283
- if (this.#isBackgroundFetch(v)) return 0;
10284
- if (!isPosInt(size)) {
10285
- if (sizeCalculation) {
10286
- if (typeof sizeCalculation !== "function") throw new TypeError("sizeCalculation must be a function");
10287
- size = sizeCalculation(v, k);
10288
- if (!isPosInt(size)) throw new TypeError("sizeCalculation return invalid (expect positive integer)");
10289
+ n = h;
10290
+ let r = setTimeout(() => n = 0, this.ttlResolution);
10291
+ r.unref && r.unref();
10292
+ }
10293
+ return h;
10294
+ };
10295
+ this.getRemainingTTL = (h) => {
10296
+ let r = this.#s.get(h);
10297
+ return r === void 0 ? 0 : l(r);
10298
+ };
10299
+ let l = (h) => {
10300
+ let r = e[h], c = t[h];
10301
+ if (!r || !c) return 1 / 0;
10302
+ return r - ((n || o()) - c);
10303
+ };
10304
+ this.#p = (h) => {
10305
+ let r = t[h], c = e[h];
10306
+ return !!c && !!r && (n || o()) - r > c;
10307
+ };
10308
+ }
10309
+ #R = () => {};
10310
+ #v = () => {};
10311
+ #H = () => {};
10312
+ #p = () => !1;
10313
+ #X() {
10314
+ let e = new O(this.#o);
10315
+ this.#b = 0, this.#_ = e, this.#x = (t) => {
10316
+ this.#b -= e[t], e[t] = 0;
10317
+ }, this.#N = (t, i, s, n) => {
10318
+ if (!T(s)) {
10319
+ if (this.#e(i)) return this.backgroundFetchSize;
10320
+ if (n) {
10321
+ if (typeof n != "function") throw new TypeError("sizeCalculation must be a function");
10322
+ if (s = n(i, t), !T(s)) throw new TypeError("sizeCalculation return invalid (expect positive integer)");
10289
10323
  } else throw new TypeError("invalid size value (must be positive integer). When maxSize or maxEntrySize is used, sizeCalculation or size must be set.");
10290
10324
  }
10291
- return size;
10292
- };
10293
- this.#addItemSize = (index, size, status) => {
10294
- sizes[index] = size;
10295
- if (this.#maxSize) {
10296
- const maxSize = this.#maxSize - sizes[index];
10297
- while (this.#calculatedSize > maxSize) this.#evict(true);
10298
- }
10299
- this.#calculatedSize += sizes[index];
10300
- if (status) {
10301
- status.entrySize = size;
10302
- status.totalCalculatedSize = this.#calculatedSize;
10325
+ return s;
10326
+ }, this.#j = (t, i, s) => {
10327
+ if (e[t] = i, this.#c) {
10328
+ let n = this.#c - e[t];
10329
+ for (; this.#b > n;) this.#G(!0);
10303
10330
  }
10331
+ this.#b += e[t], s && (s.entrySize = i, s.totalCalculatedSize = this.#b);
10304
10332
  };
10305
10333
  }
10306
- #removeItemSize = (_i) => {};
10307
- #addItemSize = (_i, _s, _st) => {};
10308
- #requireSize = (_k, _v, size, sizeCalculation) => {
10309
- if (size || sizeCalculation) throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");
10334
+ #x = (e) => {};
10335
+ #j = (e, t, i) => {};
10336
+ #N = (e, t, i, s) => {
10337
+ if (i || s) throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");
10310
10338
  return 0;
10311
10339
  };
10312
- *#indexes({ allowStale = this.allowStale } = {}) {
10313
- if (this.#size) for (let i = this.#tail;;) {
10314
- if (!this.#isValidIndex(i)) break;
10315
- if (allowStale || !this.#isStale(i)) yield i;
10316
- if (i === this.#head) break;
10317
- else i = this.#prev[i];
10318
- }
10340
+ *#A({ allowStale: e = this.allowStale } = {}) {
10341
+ if (this.#n) for (let t = this.#h; this.#V(t) && ((e || !this.#p(t)) && (yield t), t !== this.#a);) t = this.#u[t];
10319
10342
  }
10320
- *#rindexes({ allowStale = this.allowStale } = {}) {
10321
- if (this.#size) for (let i = this.#head;;) {
10322
- if (!this.#isValidIndex(i)) break;
10323
- if (allowStale || !this.#isStale(i)) yield i;
10324
- if (i === this.#tail) break;
10325
- else i = this.#next[i];
10326
- }
10343
+ *#z({ allowStale: e = this.allowStale } = {}) {
10344
+ if (this.#n) for (let t = this.#a; this.#V(t) && ((e || !this.#p(t)) && (yield t), t !== this.#h);) t = this.#l[t];
10327
10345
  }
10328
- #isValidIndex(index) {
10329
- return index !== void 0 && this.#keyMap.get(this.#keyList[index]) === index;
10346
+ #V(e) {
10347
+ return e !== void 0 && this.#s.get(this.#i[e]) === e;
10330
10348
  }
10331
- /**
10332
- * Return a generator yielding `[key, value]` pairs,
10333
- * in order from most recently used to least recently used.
10334
- */
10335
10349
  *entries() {
10336
- for (const i of this.#indexes()) if (this.#valList[i] !== void 0 && this.#keyList[i] !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) yield [this.#keyList[i], this.#valList[i]];
10350
+ for (let e of this.#A()) this.#t[e] !== void 0 && this.#i[e] !== void 0 && !this.#e(this.#t[e]) && (yield [this.#i[e], this.#t[e]]);
10337
10351
  }
10338
- /**
10339
- * Inverse order version of {@link LRUCache.entries}
10340
- *
10341
- * Return a generator yielding `[key, value]` pairs,
10342
- * in order from least recently used to most recently used.
10343
- */
10344
10352
  *rentries() {
10345
- for (const i of this.#rindexes()) if (this.#valList[i] !== void 0 && this.#keyList[i] !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) yield [this.#keyList[i], this.#valList[i]];
10353
+ for (let e of this.#z()) this.#t[e] !== void 0 && this.#i[e] !== void 0 && !this.#e(this.#t[e]) && (yield [this.#i[e], this.#t[e]]);
10346
10354
  }
10347
- /**
10348
- * Return a generator yielding the keys in the cache,
10349
- * in order from most recently used to least recently used.
10350
- */
10351
10355
  *keys() {
10352
- for (const i of this.#indexes()) {
10353
- const k = this.#keyList[i];
10354
- if (k !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) yield k;
10356
+ for (let e of this.#A()) {
10357
+ let t = this.#i[e];
10358
+ t !== void 0 && !this.#e(this.#t[e]) && (yield t);
10355
10359
  }
10356
10360
  }
10357
- /**
10358
- * Inverse order version of {@link LRUCache.keys}
10359
- *
10360
- * Return a generator yielding the keys in the cache,
10361
- * in order from least recently used to most recently used.
10362
- */
10363
10361
  *rkeys() {
10364
- for (const i of this.#rindexes()) {
10365
- const k = this.#keyList[i];
10366
- if (k !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) yield k;
10362
+ for (let e of this.#z()) {
10363
+ let t = this.#i[e];
10364
+ t !== void 0 && !this.#e(this.#t[e]) && (yield t);
10367
10365
  }
10368
10366
  }
10369
- /**
10370
- * Return a generator yielding the values in the cache,
10371
- * in order from most recently used to least recently used.
10372
- */
10373
10367
  *values() {
10374
- for (const i of this.#indexes()) if (this.#valList[i] !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) yield this.#valList[i];
10368
+ for (let e of this.#A()) this.#t[e] !== void 0 && !this.#e(this.#t[e]) && (yield this.#t[e]);
10375
10369
  }
10376
- /**
10377
- * Inverse order version of {@link LRUCache.values}
10378
- *
10379
- * Return a generator yielding the values in the cache,
10380
- * in order from least recently used to most recently used.
10381
- */
10382
10370
  *rvalues() {
10383
- for (const i of this.#rindexes()) if (this.#valList[i] !== void 0 && !this.#isBackgroundFetch(this.#valList[i])) yield this.#valList[i];
10371
+ for (let e of this.#z()) this.#t[e] !== void 0 && !this.#e(this.#t[e]) && (yield this.#t[e]);
10384
10372
  }
10385
- /**
10386
- * Iterating over the cache itself yields the same results as
10387
- * {@link LRUCache.entries}
10388
- */
10389
10373
  [Symbol.iterator]() {
10390
10374
  return this.entries();
10391
10375
  }
10392
- /**
10393
- * A String value that is used in the creation of the default string
10394
- * description of an object. Called by the built-in method
10395
- * `Object.prototype.toString`.
10396
- */
10397
10376
  [Symbol.toStringTag] = "LRUCache";
10398
- /**
10399
- * Find a value for which the supplied fn method returns a truthy value,
10400
- * similar to `Array.find()`. fn is called as `fn(value, key, cache)`.
10401
- */
10402
- find(fn, getOptions = {}) {
10403
- for (const i of this.#indexes()) {
10404
- const v = this.#valList[i];
10405
- const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
10406
- if (value === void 0) continue;
10407
- if (fn(value, this.#keyList[i], this)) return this.get(this.#keyList[i], getOptions);
10377
+ find(e, t = {}) {
10378
+ for (let i of this.#A()) {
10379
+ let s = this.#t[i], n = this.#e(s) ? s.__staleWhileFetching : s;
10380
+ if (n !== void 0 && e(n, this.#i[i], this)) return this.#C(this.#i[i], t);
10408
10381
  }
10409
10382
  }
10410
- /**
10411
- * Call the supplied function on each item in the cache, in order from most
10412
- * recently used to least recently used.
10413
- *
10414
- * `fn` is called as `fn(value, key, cache)`.
10415
- *
10416
- * If `thisp` is provided, function will be called in the `this`-context of
10417
- * the provided object, or the cache if no `thisp` object is provided.
10418
- *
10419
- * Does not update age or recenty of use, or iterate over stale values.
10420
- */
10421
- forEach(fn, thisp = this) {
10422
- for (const i of this.#indexes()) {
10423
- const v = this.#valList[i];
10424
- const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
10425
- if (value === void 0) continue;
10426
- fn.call(thisp, value, this.#keyList[i], this);
10383
+ forEach(e, t = this) {
10384
+ for (let i of this.#A()) {
10385
+ let s = this.#t[i], n = this.#e(s) ? s.__staleWhileFetching : s;
10386
+ n !== void 0 && e.call(t, n, this.#i[i], this);
10427
10387
  }
10428
10388
  }
10429
- /**
10430
- * The same as {@link LRUCache.forEach} but items are iterated over in
10431
- * reverse order. (ie, less recently used items are iterated over first.)
10432
- */
10433
- rforEach(fn, thisp = this) {
10434
- for (const i of this.#rindexes()) {
10435
- const v = this.#valList[i];
10436
- const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
10437
- if (value === void 0) continue;
10438
- fn.call(thisp, value, this.#keyList[i], this);
10389
+ rforEach(e, t = this) {
10390
+ for (let i of this.#z()) {
10391
+ let s = this.#t[i], n = this.#e(s) ? s.__staleWhileFetching : s;
10392
+ n !== void 0 && e.call(t, n, this.#i[i], this);
10439
10393
  }
10440
10394
  }
10441
- /**
10442
- * Delete any stale entries. Returns true if anything was removed,
10443
- * false otherwise.
10444
- */
10445
10395
  purgeStale() {
10446
- let deleted = false;
10447
- for (const i of this.#rindexes({ allowStale: true })) if (this.#isStale(i)) {
10448
- this.#delete(this.#keyList[i], "expire");
10449
- deleted = true;
10450
- }
10451
- return deleted;
10452
- }
10453
- /**
10454
- * Get the extended info about a given entry, to get its value, size, and
10455
- * TTL info simultaneously. Returns `undefined` if the key is not present.
10456
- *
10457
- * Unlike {@link LRUCache#dump}, which is designed to be portable and survive
10458
- * serialization, the `start` value is always the current timestamp, and the
10459
- * `ttl` is a calculated remaining time to live (negative if expired).
10460
- *
10461
- * Always returns stale values, if their info is found in the cache, so be
10462
- * sure to check for expirations (ie, a negative {@link LRUCache.Entry#ttl})
10463
- * if relevant.
10464
- */
10465
- info(key) {
10466
- const i = this.#keyMap.get(key);
10467
- if (i === void 0) return void 0;
10468
- const v = this.#valList[i];
10469
- /* c8 ignore start - this isn't tested for the info function,
10470
- * but it's the same logic as found in other places. */
10471
- const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
10472
- if (value === void 0) return void 0;
10473
- /* c8 ignore end */
10474
- const entry = { value };
10475
- if (this.#ttls && this.#starts) {
10476
- const ttl = this.#ttls[i];
10477
- const start = this.#starts[i];
10478
- if (ttl && start) {
10479
- entry.ttl = ttl - (this.#perf.now() - start);
10480
- entry.start = Date.now();
10481
- }
10482
- }
10483
- if (this.#sizes) entry.size = this.#sizes[i];
10484
- return entry;
10396
+ let e = !1;
10397
+ for (let t of this.#z({ allowStale: !0 })) this.#p(t) && (this.#E(this.#i[t], "expire"), e = !0);
10398
+ return e;
10399
+ }
10400
+ info(e) {
10401
+ let t = this.#s.get(e);
10402
+ if (t === void 0) return;
10403
+ let i = this.#t[t], s = this.#e(i) ? i.__staleWhileFetching : i;
10404
+ if (s === void 0) return;
10405
+ let n = { value: s };
10406
+ if (this.#d && this.#F) {
10407
+ let o = this.#d[t], l = this.#F[t];
10408
+ if (o && l) n.ttl = o - (this.#m.now() - l), n.start = Date.now();
10409
+ }
10410
+ return this.#_ && (n.size = this.#_[t]), n;
10485
10411
  }
10486
- /**
10487
- * Return an array of [key, {@link LRUCache.Entry}] tuples which can be
10488
- * passed to {@link LRUCache#load}.
10489
- *
10490
- * The `start` fields are calculated relative to a portable `Date.now()`
10491
- * timestamp, even if `performance.now()` is available.
10492
- *
10493
- * Stale entries are always included in the `dump`, even if
10494
- * {@link LRUCache.OptionsBase.allowStale} is false.
10495
- *
10496
- * Note: this returns an actual array, not a generator, so it can be more
10497
- * easily passed around.
10498
- */
10499
10412
  dump() {
10500
- const arr = [];
10501
- for (const i of this.#indexes({ allowStale: true })) {
10502
- const key = this.#keyList[i];
10503
- const v = this.#valList[i];
10504
- const value = this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
10505
- if (value === void 0 || key === void 0) continue;
10506
- const entry = { value };
10507
- if (this.#ttls && this.#starts) {
10508
- entry.ttl = this.#ttls[i];
10509
- const age = this.#perf.now() - this.#starts[i];
10510
- entry.start = Math.floor(Date.now() - age);
10511
- }
10512
- if (this.#sizes) entry.size = this.#sizes[i];
10513
- arr.unshift([key, entry]);
10514
- }
10515
- return arr;
10516
- }
10517
- /**
10518
- * Reset the cache and load in the items in entries in the order listed.
10519
- *
10520
- * The shape of the resulting cache may be different if the same options are
10521
- * not used in both caches.
10522
- *
10523
- * The `start` fields are assumed to be calculated relative to a portable
10524
- * `Date.now()` timestamp, even if `performance.now()` is available.
10525
- */
10526
- load(arr) {
10527
- this.clear();
10528
- for (const [key, entry] of arr) {
10529
- if (entry.start) {
10530
- const age = Date.now() - entry.start;
10531
- entry.start = this.#perf.now() - age;
10413
+ let e = [];
10414
+ for (let t of this.#A({ allowStale: !0 })) {
10415
+ let i = this.#i[t], s = this.#t[t], n = this.#e(s) ? s.__staleWhileFetching : s;
10416
+ if (n === void 0 || i === void 0) continue;
10417
+ let o = { value: n };
10418
+ if (this.#d && this.#F) {
10419
+ o.ttl = this.#d[t];
10420
+ let l = this.#m.now() - this.#F[t];
10421
+ o.start = Math.floor(Date.now() - l);
10532
10422
  }
10533
- this.set(key, entry.value, entry);
10423
+ this.#_ && (o.size = this.#_[t]), e.unshift([i, o]);
10534
10424
  }
10425
+ return e;
10535
10426
  }
10536
- /**
10537
- * Add a value to the cache.
10538
- *
10539
- * Note: if `undefined` is specified as a value, this is an alias for
10540
- * {@link LRUCache#delete}
10541
- *
10542
- * Fields on the {@link LRUCache.SetOptions} options param will override
10543
- * their corresponding values in the constructor options for the scope
10544
- * of this single `set()` operation.
10545
- *
10546
- * If `start` is provided, then that will set the effective start
10547
- * time for the TTL calculation. Note that this must be a previous
10548
- * value of `performance.now()` if supported, or a previous value of
10549
- * `Date.now()` if not.
10550
- *
10551
- * Options object may also include `size`, which will prevent
10552
- * calling the `sizeCalculation` function and just use the specified
10553
- * number if it is a positive integer, and `noDisposeOnSet` which
10554
- * will prevent calling a `dispose` function in the case of
10555
- * overwrites.
10556
- *
10557
- * If the `size` (or return value of `sizeCalculation`) for a given
10558
- * entry is greater than `maxEntrySize`, then the item will not be
10559
- * added to the cache.
10560
- *
10561
- * Will update the recency of the entry.
10562
- *
10563
- * If the value is `undefined`, then this is an alias for
10564
- * `cache.delete(key)`. `undefined` is never stored in the cache.
10565
- */
10566
- set(k, v, setOptions = {}) {
10567
- if (v === void 0) {
10568
- this.delete(k);
10569
- return this;
10570
- }
10571
- const { ttl = this.ttl, start, noDisposeOnSet = this.noDisposeOnSet, sizeCalculation = this.sizeCalculation, status } = setOptions;
10572
- let { noUpdateTTL = this.noUpdateTTL } = setOptions;
10573
- const size = this.#requireSize(k, v, setOptions.size || 0, sizeCalculation);
10574
- if (this.maxEntrySize && size > this.maxEntrySize) {
10575
- if (status) {
10576
- status.set = "miss";
10577
- status.maxEntrySizeExceeded = true;
10578
- }
10579
- this.#delete(k, "set");
10580
- return this;
10581
- }
10582
- let index = this.#size === 0 ? void 0 : this.#keyMap.get(k);
10583
- if (index === void 0) {
10584
- index = this.#size === 0 ? this.#tail : this.#free.length !== 0 ? this.#free.pop() : this.#size === this.#max ? this.#evict(false) : this.#size;
10585
- this.#keyList[index] = k;
10586
- this.#valList[index] = v;
10587
- this.#keyMap.set(k, index);
10588
- this.#next[this.#tail] = index;
10589
- this.#prev[index] = this.#tail;
10590
- this.#tail = index;
10591
- this.#size++;
10592
- this.#addItemSize(index, size, status);
10593
- if (status) status.set = "add";
10594
- noUpdateTTL = false;
10595
- if (this.#hasOnInsert) this.#onInsert?.(v, k, "add");
10596
- } else {
10597
- this.#moveToTail(index);
10598
- const oldVal = this.#valList[index];
10599
- if (v !== oldVal) {
10600
- if (this.#hasFetchMethod && this.#isBackgroundFetch(oldVal)) {
10601
- oldVal.__abortController.abort(/* @__PURE__ */ new Error("replaced"));
10602
- const { __staleWhileFetching: s } = oldVal;
10603
- if (s !== void 0 && !noDisposeOnSet) {
10604
- if (this.#hasDispose) this.#dispose?.(s, k, "set");
10605
- if (this.#hasDisposeAfter) this.#disposed?.push([
10606
- s,
10607
- k,
10608
- "set"
10609
- ]);
10610
- }
10611
- } else if (!noDisposeOnSet) {
10612
- if (this.#hasDispose) this.#dispose?.(oldVal, k, "set");
10613
- if (this.#hasDisposeAfter) this.#disposed?.push([
10614
- oldVal,
10615
- k,
10427
+ load(e) {
10428
+ this.clear();
10429
+ for (let [t, i] of e) {
10430
+ if (i.start) {
10431
+ let s = Date.now() - i.start;
10432
+ i.start = this.#m.now() - s;
10433
+ }
10434
+ this.#W(t, i.value, i);
10435
+ }
10436
+ }
10437
+ set(e, t, i = {}) {
10438
+ let { status: s = S.hasSubscribers ? {} : void 0 } = i;
10439
+ i.status = s, s && (s.op = "set", s.key = e, t !== void 0 && (s.value = t), s.cache = this);
10440
+ let n = this.#W(e, t, i);
10441
+ return s && S.hasSubscribers && S.publish(s), n;
10442
+ }
10443
+ #W(e, t, i, s) {
10444
+ let { ttl: n = this.ttl, start: o, noDisposeOnSet: l = this.noDisposeOnSet, sizeCalculation: h = this.sizeCalculation, status: r } = i, c = this.#e(t);
10445
+ if (t === void 0) return r && (r.set = "deleted"), this.delete(e), this;
10446
+ let { noUpdateTTL: m = this.noUpdateTTL } = i;
10447
+ r && !c && (r.value = t);
10448
+ let _ = this.#N(e, t, i.size || 0, h, r);
10449
+ if (this.maxEntrySize && _ > this.maxEntrySize) return this.#E(e, "set"), r && (r.set = "miss", r.maxEntrySizeExceeded = !0), this;
10450
+ let u = this.#n === 0 ? void 0 : this.#s.get(e);
10451
+ if (u === void 0) u = this.#n === 0 ? this.#h : this.#y.length !== 0 ? this.#y.pop() : this.#n === this.#o ? this.#G(!1) : this.#n, this.#i[u] = e, this.#t[u] = t, this.#s.set(e, u), this.#l[this.#h] = u, this.#u[u] = this.#h, this.#h = u, this.#n++, this.#j(u, _, r), r && (r.set = "add"), m = !1, this.#D && !c && this.#O?.(t, e, "add");
10452
+ else {
10453
+ this.#L(u);
10454
+ let g = this.#t[u];
10455
+ if (t !== g) {
10456
+ if (!l) if (this.#e(g)) {
10457
+ g !== s && g.__abortController.abort(/* @__PURE__ */ new Error("replaced"));
10458
+ let { __staleWhileFetching: f } = g;
10459
+ f !== void 0 && f !== t && (this.#T && this.#S?.(f, e, "set"), this.#f && this.#r?.push([
10460
+ f,
10461
+ e,
10616
10462
  "set"
10617
- ]);
10618
- }
10619
- this.#removeItemSize(index);
10620
- this.#addItemSize(index, size, status);
10621
- this.#valList[index] = v;
10622
- if (status) {
10623
- status.set = "replace";
10624
- const oldValue = oldVal && this.#isBackgroundFetch(oldVal) ? oldVal.__staleWhileFetching : oldVal;
10625
- if (oldValue !== void 0) status.oldValue = oldValue;
10463
+ ]));
10464
+ } else this.#T && this.#S?.(g, e, "set"), this.#f && this.#r?.push([
10465
+ g,
10466
+ e,
10467
+ "set"
10468
+ ]);
10469
+ if (this.#x(u), this.#j(u, _, r), this.#t[u] = t, !c) {
10470
+ let f = g && this.#e(g) ? g.__staleWhileFetching : g, y = f === void 0 ? "add" : t !== f ? "replace" : "update";
10471
+ r && (r.set = y, f !== void 0 && (r.oldValue = f)), this.#D && this.onInsert?.(t, e, y);
10626
10472
  }
10627
- } else if (status) status.set = "update";
10628
- if (this.#hasOnInsert) this.onInsert?.(v, k, v === oldVal ? "update" : "replace");
10473
+ } else c || (r && (r.set = "update"), this.#D && this.onInsert?.(t, e, "update"));
10629
10474
  }
10630
- if (ttl !== 0 && !this.#ttls) this.#initializeTTLTracking();
10631
- if (this.#ttls) {
10632
- if (!noUpdateTTL) this.#setItemTTL(index, ttl, start);
10633
- if (status) this.#statusTTL(status, index);
10634
- }
10635
- if (!noDisposeOnSet && this.#hasDisposeAfter && this.#disposed) {
10636
- const dt = this.#disposed;
10637
- let task;
10638
- while (task = dt?.shift()) this.#disposeAfter?.(...task);
10475
+ if (n !== 0 && !this.#d && this.#k(), this.#d && (m || this.#H(u, n, o), r && this.#v(r, u)), !l && this.#f && this.#r) {
10476
+ let g = this.#r, f;
10477
+ for (; f = g?.shift();) this.#w?.(...f);
10639
10478
  }
10640
10479
  return this;
10641
10480
  }
10642
- /**
10643
- * Evict the least recently used item, returning its value or
10644
- * `undefined` if cache is empty.
10645
- */
10646
10481
  pop() {
10647
10482
  try {
10648
- while (this.#size) {
10649
- const val = this.#valList[this.#head];
10650
- this.#evict(true);
10651
- if (this.#isBackgroundFetch(val)) {
10652
- if (val.__staleWhileFetching) return val.__staleWhileFetching;
10653
- } else if (val !== void 0) return val;
10483
+ for (; this.#n;) {
10484
+ let e = this.#t[this.#a];
10485
+ if (this.#G(!0), this.#e(e)) {
10486
+ if (e.__staleWhileFetching) return e.__staleWhileFetching;
10487
+ } else if (e !== void 0) return e;
10654
10488
  }
10655
10489
  } finally {
10656
- if (this.#hasDisposeAfter && this.#disposed) {
10657
- const dt = this.#disposed;
10658
- let task;
10659
- while (task = dt?.shift()) this.#disposeAfter?.(...task);
10660
- }
10661
- }
10662
- }
10663
- #evict(free) {
10664
- const head = this.#head;
10665
- const k = this.#keyList[head];
10666
- const v = this.#valList[head];
10667
- if (this.#hasFetchMethod && this.#isBackgroundFetch(v)) v.__abortController.abort(/* @__PURE__ */ new Error("evicted"));
10668
- else if (this.#hasDispose || this.#hasDisposeAfter) {
10669
- if (this.#hasDispose) this.#dispose?.(v, k, "evict");
10670
- if (this.#hasDisposeAfter) this.#disposed?.push([
10671
- v,
10672
- k,
10673
- "evict"
10674
- ]);
10675
- }
10676
- this.#removeItemSize(head);
10677
- if (this.#autopurgeTimers?.[head]) {
10678
- clearTimeout(this.#autopurgeTimers[head]);
10679
- this.#autopurgeTimers[head] = void 0;
10680
- }
10681
- if (free) {
10682
- this.#keyList[head] = void 0;
10683
- this.#valList[head] = void 0;
10684
- this.#free.push(head);
10685
- }
10686
- if (this.#size === 1) {
10687
- this.#head = this.#tail = 0;
10688
- this.#free.length = 0;
10689
- } else this.#head = this.#next[head];
10690
- this.#keyMap.delete(k);
10691
- this.#size--;
10692
- return head;
10693
- }
10694
- /**
10695
- * Check if a key is in the cache, without updating the recency of use.
10696
- * Will return false if the item is stale, even though it is technically
10697
- * in the cache.
10698
- *
10699
- * Check if a key is in the cache, without updating the recency of
10700
- * use. Age is updated if {@link LRUCache.OptionsBase.updateAgeOnHas} is set
10701
- * to `true` in either the options or the constructor.
10702
- *
10703
- * Will return `false` if the item is stale, even though it is technically in
10704
- * the cache. The difference can be determined (if it matters) by using a
10705
- * `status` argument, and inspecting the `has` field.
10706
- *
10707
- * Will not update item age unless
10708
- * {@link LRUCache.OptionsBase.updateAgeOnHas} is set.
10709
- */
10710
- has(k, hasOptions = {}) {
10711
- const { updateAgeOnHas = this.updateAgeOnHas, status } = hasOptions;
10712
- const index = this.#keyMap.get(k);
10713
- if (index !== void 0) {
10714
- const v = this.#valList[index];
10715
- if (this.#isBackgroundFetch(v) && v.__staleWhileFetching === void 0) return false;
10716
- if (!this.#isStale(index)) {
10717
- if (updateAgeOnHas) this.#updateItemAge(index);
10718
- if (status) {
10719
- status.has = "hit";
10720
- this.#statusTTL(status, index);
10721
- }
10722
- return true;
10723
- } else if (status) {
10724
- status.has = "stale";
10725
- this.#statusTTL(status, index);
10726
- }
10727
- } else if (status) status.has = "miss";
10728
- return false;
10729
- }
10730
- /**
10731
- * Like {@link LRUCache#get} but doesn't update recency or delete stale
10732
- * items.
10733
- *
10734
- * Returns `undefined` if the item is stale, unless
10735
- * {@link LRUCache.OptionsBase.allowStale} is set.
10736
- */
10737
- peek(k, peekOptions = {}) {
10738
- const { allowStale = this.allowStale } = peekOptions;
10739
- const index = this.#keyMap.get(k);
10740
- if (index === void 0 || !allowStale && this.#isStale(index)) return;
10741
- const v = this.#valList[index];
10742
- return this.#isBackgroundFetch(v) ? v.__staleWhileFetching : v;
10743
- }
10744
- #backgroundFetch(k, index, options, context) {
10745
- const v = index === void 0 ? void 0 : this.#valList[index];
10746
- if (this.#isBackgroundFetch(v)) return v;
10747
- const ac = new AC();
10748
- const { signal } = options;
10749
- signal?.addEventListener("abort", () => ac.abort(signal.reason), { signal: ac.signal });
10750
- const fetchOpts = {
10751
- signal: ac.signal,
10752
- options,
10753
- context
10754
- };
10755
- const cb = (v, updateCache = false) => {
10756
- const { aborted } = ac.signal;
10757
- const ignoreAbort = options.ignoreFetchAbort && v !== void 0;
10758
- if (options.status) {
10759
- if (aborted && !updateCache) {
10760
- options.status.fetchAborted = true;
10761
- options.status.fetchError = ac.signal.reason;
10762
- if (ignoreAbort) options.status.fetchAbortIgnored = true;
10763
- } else options.status.fetchResolved = true;
10764
- }
10765
- if (aborted && !ignoreAbort && !updateCache) return fetchFail(ac.signal.reason);
10766
- const bf = p;
10767
- const vl = this.#valList[index];
10768
- if (vl === p || ignoreAbort && updateCache && vl === void 0) {
10769
- if (v === void 0) {
10770
- if (bf.__staleWhileFetching !== void 0) this.#valList[index] = bf.__staleWhileFetching;
10771
- else this.#delete(k, "fetch");
10772
- } else {
10773
- if (options.status) options.status.fetchUpdated = true;
10774
- this.set(k, v, fetchOpts.options);
10775
- }
10776
- }
10777
- return v;
10778
- };
10779
- const eb = (er) => {
10780
- if (options.status) {
10781
- options.status.fetchRejected = true;
10782
- options.status.fetchError = er;
10783
- }
10784
- return fetchFail(er);
10785
- };
10786
- const fetchFail = (er) => {
10787
- const { aborted } = ac.signal;
10788
- const allowStaleAborted = aborted && options.allowStaleOnFetchAbort;
10789
- const allowStale = allowStaleAborted || options.allowStaleOnFetchRejection;
10790
- const noDelete = allowStale || options.noDeleteOnFetchRejection;
10791
- const bf = p;
10792
- if (this.#valList[index] === p) {
10793
- if (!noDelete || bf.__staleWhileFetching === void 0) this.#delete(k, "fetch");
10794
- else if (!allowStaleAborted) this.#valList[index] = bf.__staleWhileFetching;
10795
- }
10796
- if (allowStale) {
10797
- if (options.status && bf.__staleWhileFetching !== void 0) options.status.returnedStale = true;
10798
- return bf.__staleWhileFetching;
10799
- } else if (bf.__returned === bf) throw er;
10800
- };
10801
- const pcall = (res, rej) => {
10802
- const fmp = this.#fetchMethod?.(k, v, fetchOpts);
10803
- if (fmp && fmp instanceof Promise) fmp.then((v) => res(v === void 0 ? void 0 : v), rej);
10804
- ac.signal.addEventListener("abort", () => {
10805
- if (!options.ignoreFetchAbort || options.allowStaleOnFetchAbort) {
10806
- res(void 0);
10807
- if (options.allowStaleOnFetchAbort) res = (v) => cb(v, true);
10808
- }
10809
- });
10810
- };
10811
- if (options.status) options.status.fetchDispatched = true;
10812
- const p = new Promise(pcall).then(cb, eb);
10813
- const bf = Object.assign(p, {
10814
- __abortController: ac,
10815
- __staleWhileFetching: v,
10490
+ if (this.#f && this.#r) {
10491
+ let e = this.#r, t;
10492
+ for (; t = e?.shift();) this.#w?.(...t);
10493
+ }
10494
+ }
10495
+ }
10496
+ #G(e) {
10497
+ let t = this.#a, i = this.#i[t], s = this.#t[t], n = this.#e(s);
10498
+ n && s.__abortController.abort(/* @__PURE__ */ new Error("evicted"));
10499
+ let o = n ? s.__staleWhileFetching : s;
10500
+ return (this.#T || this.#f) && o !== void 0 && (this.#T && this.#S?.(o, i, "evict"), this.#f && this.#r?.push([
10501
+ o,
10502
+ i,
10503
+ "evict"
10504
+ ])), this.#x(t), this.#g?.[t] && (clearTimeout(this.#g[t]), this.#g[t] = void 0), e && (this.#i[t] = void 0, this.#t[t] = void 0, this.#y.push(t)), this.#n === 1 ? (this.#a = this.#h = 0, this.#y.length = 0) : this.#a = this.#l[t], this.#s.delete(i), this.#n--, t;
10505
+ }
10506
+ has(e, t = {}) {
10507
+ let { status: i = S.hasSubscribers ? {} : void 0 } = t;
10508
+ t.status = i, i && (i.op = "has", i.key = e, i.cache = this);
10509
+ let s = this.#Y(e, t);
10510
+ return S.hasSubscribers && S.publish(i), s;
10511
+ }
10512
+ #Y(e, t = {}) {
10513
+ let { updateAgeOnHas: i = this.updateAgeOnHas, status: s } = t, n = this.#s.get(e);
10514
+ if (n !== void 0) {
10515
+ let o = this.#t[n];
10516
+ if (this.#e(o) && o.__staleWhileFetching === void 0) return !1;
10517
+ if (this.#p(n)) s && (s.has = "stale", this.#v(s, n));
10518
+ else return i && this.#R(n), s && (s.has = "hit", this.#v(s, n)), !0;
10519
+ } else s && (s.has = "miss");
10520
+ return !1;
10521
+ }
10522
+ peek(e, t = {}) {
10523
+ let { status: i = R() ? {} : void 0 } = t;
10524
+ i && (i.op = "peek", i.key = e, i.cache = this), t.status = i;
10525
+ let s = this.#J(e, t);
10526
+ return S.hasSubscribers && S.publish(i), s;
10527
+ }
10528
+ #J(e, t) {
10529
+ let { status: i, allowStale: s = this.allowStale } = t, n = this.#s.get(e);
10530
+ if (n === void 0 || !s && this.#p(n)) {
10531
+ i && (i.peek = n === void 0 ? "miss" : "stale");
10532
+ return;
10533
+ }
10534
+ let o = this.#t[n], l = this.#e(o) ? o.__staleWhileFetching : o;
10535
+ return i && (l !== void 0 ? (i.peek = "hit", i.value = l) : i.peek = "miss"), l;
10536
+ }
10537
+ #P(e, t, i, s) {
10538
+ let n = t === void 0 ? void 0 : this.#t[t];
10539
+ if (this.#e(n)) return n;
10540
+ let o = new AbortController(), { signal: l } = i;
10541
+ l?.addEventListener("abort", () => o.abort(l.reason), { signal: o.signal });
10542
+ let h = {
10543
+ signal: o.signal,
10544
+ options: i,
10545
+ context: s
10546
+ }, r = (f, y = !1) => {
10547
+ let { aborted: a } = o.signal, w = i.ignoreFetchAbort && f !== void 0, F = i.ignoreFetchAbort || !!(i.allowStaleOnFetchAbort && f !== void 0);
10548
+ if (i.status && (a && !y ? (i.status.fetchAborted = !0, i.status.fetchError = o.signal.reason, w && (i.status.fetchAbortIgnored = !0)) : i.status.fetchResolved = !0), a && !w && !y) return m(o.signal.reason, F);
10549
+ let b = u, p = this.#t[t];
10550
+ return (p === u || p === void 0 && w && y) && (f === void 0 ? b.__staleWhileFetching !== void 0 ? this.#t[t] = b.__staleWhileFetching : this.#E(e, "fetch") : (i.status && (i.status.fetchUpdated = !0), this.#W(e, f, h.options, b))), f;
10551
+ }, c = (f) => (i.status && (i.status.fetchRejected = !0, i.status.fetchError = f), m(f, !1)), m = (f, y) => {
10552
+ let { aborted: a } = o.signal, w = a && i.allowStaleOnFetchAbort, F = w || i.allowStaleOnFetchRejection, b = F || i.noDeleteOnFetchRejection, p = u;
10553
+ if (this.#t[t] === u && (!b || !y && p.__staleWhileFetching === void 0 ? this.#E(e, "fetch") : w || (this.#t[t] = p.__staleWhileFetching)), F) return i.status && p.__staleWhileFetching !== void 0 && (i.status.returnedStale = !0), p.__staleWhileFetching;
10554
+ if (p.__returned === p) throw f;
10555
+ }, _ = (f, y) => {
10556
+ let a = this.#M?.(e, n, h);
10557
+ o.signal.addEventListener("abort", () => {
10558
+ (!i.ignoreFetchAbort || i.allowStaleOnFetchAbort) && (f(void 0), i.allowStaleOnFetchAbort && (f = (w) => r(w, !0)));
10559
+ }), a && a instanceof Promise ? a.then((w) => f(w === void 0 ? void 0 : w), y) : a !== void 0 && f(a);
10560
+ };
10561
+ i.status && (i.status.fetchDispatched = !0);
10562
+ let u = new Promise(_).then(r, c), g = Object.assign(u, {
10563
+ __abortController: o,
10564
+ __staleWhileFetching: n,
10816
10565
  __returned: void 0
10817
10566
  });
10818
- if (index === void 0) {
10819
- this.set(k, bf, {
10820
- ...fetchOpts.options,
10821
- status: void 0
10822
- });
10823
- index = this.#keyMap.get(k);
10824
- } else this.#valList[index] = bf;
10825
- return bf;
10826
- }
10827
- #isBackgroundFetch(p) {
10828
- if (!this.#hasFetchMethod) return false;
10829
- const b = p;
10830
- return !!b && b instanceof Promise && b.hasOwnProperty("__staleWhileFetching") && b.__abortController instanceof AC;
10831
- }
10832
- async fetch(k, fetchOptions = {}) {
10833
- const { allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet, ttl = this.ttl, noDisposeOnSet = this.noDisposeOnSet, size = 0, sizeCalculation = this.sizeCalculation, noUpdateTTL = this.noUpdateTTL, noDeleteOnFetchRejection = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection = this.allowStaleOnFetchRejection, ignoreFetchAbort = this.ignoreFetchAbort, allowStaleOnFetchAbort = this.allowStaleOnFetchAbort, context, forceRefresh = false, status, signal } = fetchOptions;
10834
- if (!this.#hasFetchMethod) {
10835
- if (status) status.fetch = "get";
10836
- return this.get(k, {
10837
- allowStale,
10838
- updateAgeOnGet,
10839
- noDeleteOnStaleGet,
10840
- status
10841
- });
10842
- }
10843
- const options = {
10844
- allowStale,
10845
- updateAgeOnGet,
10846
- noDeleteOnStaleGet,
10847
- ttl,
10848
- noDisposeOnSet,
10849
- size,
10850
- sizeCalculation,
10851
- noUpdateTTL,
10852
- noDeleteOnFetchRejection,
10853
- allowStaleOnFetchRejection,
10854
- allowStaleOnFetchAbort,
10855
- ignoreFetchAbort,
10856
- status,
10857
- signal
10858
- };
10859
- let index = this.#keyMap.get(k);
10860
- if (index === void 0) {
10861
- if (status) status.fetch = "miss";
10862
- const p = this.#backgroundFetch(k, index, options, context);
10567
+ return t === void 0 ? (this.#W(e, g, {
10568
+ ...h.options,
10569
+ status: void 0
10570
+ }), t = this.#s.get(e)) : this.#t[t] = g, g;
10571
+ }
10572
+ #e(e) {
10573
+ if (!this.#U) return !1;
10574
+ let t = e;
10575
+ return !!t && t instanceof Promise && t.hasOwnProperty("__staleWhileFetching") && t.__abortController instanceof AbortController;
10576
+ }
10577
+ fetch(e, t = {}) {
10578
+ let i = W.hasSubscribers, { status: s = R() ? {} : void 0 } = t;
10579
+ t.status = s, s && t.context && (s.context = t.context);
10580
+ let n = this.#B(e, t);
10581
+ return s && i && (s.trace = !0, W.tracePromise(() => n, s).catch(() => {})), n;
10582
+ }
10583
+ async #B(e, t = {}) {
10584
+ let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, ttl: o = this.ttl, noDisposeOnSet: l = this.noDisposeOnSet, size: h = 0, sizeCalculation: r = this.sizeCalculation, noUpdateTTL: c = this.noUpdateTTL, noDeleteOnFetchRejection: m = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection: _ = this.allowStaleOnFetchRejection, ignoreFetchAbort: u = this.ignoreFetchAbort, allowStaleOnFetchAbort: g = this.allowStaleOnFetchAbort, context: f, forceRefresh: y = !1, status: a, signal: w } = t;
10585
+ if (a && (a.op = "fetch", a.key = e, y && (a.forceRefresh = !0), a.cache = this), !this.#U) return a && (a.fetch = "get"), this.#C(e, {
10586
+ allowStale: i,
10587
+ updateAgeOnGet: s,
10588
+ noDeleteOnStaleGet: n,
10589
+ status: a
10590
+ });
10591
+ let F = {
10592
+ allowStale: i,
10593
+ updateAgeOnGet: s,
10594
+ noDeleteOnStaleGet: n,
10595
+ ttl: o,
10596
+ noDisposeOnSet: l,
10597
+ size: h,
10598
+ sizeCalculation: r,
10599
+ noUpdateTTL: c,
10600
+ noDeleteOnFetchRejection: m,
10601
+ allowStaleOnFetchRejection: _,
10602
+ allowStaleOnFetchAbort: g,
10603
+ ignoreFetchAbort: u,
10604
+ status: a,
10605
+ signal: w
10606
+ }, b = this.#s.get(e);
10607
+ if (b === void 0) {
10608
+ a && (a.fetch = "miss");
10609
+ let p = this.#P(e, b, F, f);
10863
10610
  return p.__returned = p;
10864
10611
  } else {
10865
- const v = this.#valList[index];
10866
- if (this.#isBackgroundFetch(v)) {
10867
- const stale = allowStale && v.__staleWhileFetching !== void 0;
10868
- if (status) {
10869
- status.fetch = "inflight";
10870
- if (stale) status.returnedStale = true;
10871
- }
10872
- return stale ? v.__staleWhileFetching : v.__returned = v;
10873
- }
10874
- const isStale = this.#isStale(index);
10875
- if (!forceRefresh && !isStale) {
10876
- if (status) status.fetch = "hit";
10877
- this.#moveToTail(index);
10878
- if (updateAgeOnGet) this.#updateItemAge(index);
10879
- if (status) this.#statusTTL(status, index);
10880
- return v;
10881
- }
10882
- const p = this.#backgroundFetch(k, index, options, context);
10883
- const staleVal = p.__staleWhileFetching !== void 0 && allowStale;
10884
- if (status) {
10885
- status.fetch = isStale ? "stale" : "refresh";
10886
- if (staleVal && isStale) status.returnedStale = true;
10887
- }
10888
- return staleVal ? p.__staleWhileFetching : p.__returned = p;
10889
- }
10890
- }
10891
- async forceFetch(k, fetchOptions = {}) {
10892
- const v = await this.fetch(k, fetchOptions);
10893
- if (v === void 0) throw new Error("fetch() returned undefined");
10894
- return v;
10895
- }
10896
- memo(k, memoOptions = {}) {
10897
- const memoMethod = this.#memoMethod;
10898
- if (!memoMethod) throw new Error("no memoMethod provided to constructor");
10899
- const { context, forceRefresh, ...options } = memoOptions;
10900
- const v = this.get(k, options);
10901
- if (!forceRefresh && v !== void 0) return v;
10902
- const vv = memoMethod(k, v, {
10903
- options,
10904
- context
10905
- });
10906
- this.set(k, vv, options);
10907
- return vv;
10612
+ let p = this.#t[b];
10613
+ if (this.#e(p)) {
10614
+ let v = i && p.__staleWhileFetching !== void 0;
10615
+ return a && (a.fetch = "inflight", v && (a.returnedStale = !0)), v ? p.__staleWhileFetching : p.__returned = p;
10616
+ }
10617
+ let A = this.#p(b);
10618
+ if (!y && !A) return a && (a.fetch = "hit"), this.#L(b), s && this.#R(b), a && this.#v(a, b), p;
10619
+ let z = this.#P(e, b, F, f), E = z.__staleWhileFetching !== void 0 && i;
10620
+ return a && (a.fetch = A ? "stale" : "refresh", E && A && (a.returnedStale = !0)), E ? z.__staleWhileFetching : z.__returned = z;
10621
+ }
10622
+ }
10623
+ forceFetch(e, t = {}) {
10624
+ let i = W.hasSubscribers, { status: s = R() ? {} : void 0 } = t;
10625
+ t.status = s, s && t.context && (s.context = t.context);
10626
+ let n = this.#K(e, t);
10627
+ return s && i && (s.trace = !0, W.tracePromise(() => n, s).catch(() => {})), n;
10628
+ }
10629
+ async #K(e, t = {}) {
10630
+ let i = await this.#B(e, t);
10631
+ if (i === void 0) throw new Error("fetch() returned undefined");
10632
+ return i;
10633
+ }
10634
+ memo(e, t = {}) {
10635
+ let { status: i = S.hasSubscribers ? {} : void 0 } = t;
10636
+ t.status = i, i && (i.op = "memo", i.key = e, t.context && (i.context = t.context), i.cache = this);
10637
+ let s = this.#Q(e, t);
10638
+ return i && (i.value = s), S.hasSubscribers && S.publish(i), s;
10639
+ }
10640
+ #Q(e, t = {}) {
10641
+ let i = this.#I;
10642
+ if (!i) throw new Error("no memoMethod provided to constructor");
10643
+ let { context: s, status: n, forceRefresh: o, ...l } = t;
10644
+ n && o && (n.forceRefresh = !0);
10645
+ let h = this.#C(e, l), r = o || h === void 0;
10646
+ if (n && (n.memo = r ? "miss" : "hit", r || (n.value = h)), !r) return h;
10647
+ let c = i(e, h, {
10648
+ options: l,
10649
+ context: s
10650
+ });
10651
+ return n && (n.value = c), this.#W(e, c, l), c;
10652
+ }
10653
+ get(e, t = {}) {
10654
+ let { status: i = S.hasSubscribers ? {} : void 0 } = t;
10655
+ t.status = i, i && (i.op = "get", i.key = e, i.cache = this);
10656
+ let s = this.#C(e, t);
10657
+ return i && (s !== void 0 && (i.value = s), S.hasSubscribers && S.publish(i)), s;
10658
+ }
10659
+ #C(e, t = {}) {
10660
+ let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, status: o } = t, l = this.#s.get(e);
10661
+ if (l === void 0) {
10662
+ o && (o.get = "miss");
10663
+ return;
10664
+ }
10665
+ let h = this.#t[l], r = this.#e(h);
10666
+ return o && this.#v(o, l), this.#p(l) ? r ? (o && (o.get = "stale-fetching"), i && h.__staleWhileFetching !== void 0 ? (o && (o.returnedStale = !0), h.__staleWhileFetching) : void 0) : (n || this.#E(e, "expire"), o && (o.get = "stale"), i ? (o && (o.returnedStale = !0), h) : void 0) : (o && (o.get = r ? "fetching" : "hit"), this.#L(l), s && this.#R(l), r ? h.__staleWhileFetching : h);
10908
10667
  }
10909
- /**
10910
- * Return a value from the cache. Will update the recency of the cache
10911
- * entry found.
10912
- *
10913
- * If the key is not found, get() will return `undefined`.
10914
- */
10915
- get(k, getOptions = {}) {
10916
- const { allowStale = this.allowStale, updateAgeOnGet = this.updateAgeOnGet, noDeleteOnStaleGet = this.noDeleteOnStaleGet, status } = getOptions;
10917
- const index = this.#keyMap.get(k);
10918
- if (index !== void 0) {
10919
- const value = this.#valList[index];
10920
- const fetching = this.#isBackgroundFetch(value);
10921
- if (status) this.#statusTTL(status, index);
10922
- if (this.#isStale(index)) {
10923
- if (status) status.get = "stale";
10924
- if (!fetching) {
10925
- if (!noDeleteOnStaleGet) this.#delete(k, "expire");
10926
- if (status && allowStale) status.returnedStale = true;
10927
- return allowStale ? value : void 0;
10928
- } else {
10929
- if (status && allowStale && value.__staleWhileFetching !== void 0) status.returnedStale = true;
10930
- return allowStale ? value.__staleWhileFetching : void 0;
10931
- }
10932
- } else {
10933
- if (status) status.get = "hit";
10934
- if (fetching) return value.__staleWhileFetching;
10935
- this.#moveToTail(index);
10936
- if (updateAgeOnGet) this.#updateItemAge(index);
10937
- return value;
10938
- }
10939
- } else if (status) status.get = "miss";
10668
+ #$(e, t) {
10669
+ this.#u[t] = e, this.#l[e] = t;
10940
10670
  }
10941
- #connect(p, n) {
10942
- this.#prev[n] = p;
10943
- this.#next[p] = n;
10671
+ #L(e) {
10672
+ e !== this.#h && (e === this.#a ? this.#a = this.#l[e] : this.#$(this.#u[e], this.#l[e]), this.#$(this.#h, e), this.#h = e);
10944
10673
  }
10945
- #moveToTail(index) {
10946
- if (index !== this.#tail) {
10947
- if (index === this.#head) this.#head = this.#next[index];
10948
- else this.#connect(this.#prev[index], this.#next[index]);
10949
- this.#connect(this.#tail, index);
10950
- this.#tail = index;
10951
- }
10674
+ delete(e) {
10675
+ return this.#E(e, "delete");
10952
10676
  }
10953
- /**
10954
- * Deletes a key out of the cache.
10955
- *
10956
- * Returns true if the key was deleted, false otherwise.
10957
- */
10958
- delete(k) {
10959
- return this.#delete(k, "delete");
10960
- }
10961
- #delete(k, reason) {
10962
- let deleted = false;
10963
- if (this.#size !== 0) {
10964
- const index = this.#keyMap.get(k);
10965
- if (index !== void 0) {
10966
- if (this.#autopurgeTimers?.[index]) {
10967
- clearTimeout(this.#autopurgeTimers?.[index]);
10968
- this.#autopurgeTimers[index] = void 0;
10969
- }
10970
- deleted = true;
10971
- if (this.#size === 1) this.#clear(reason);
10677
+ #E(e, t) {
10678
+ S.hasSubscribers && S.publish({
10679
+ op: "delete",
10680
+ delete: t,
10681
+ key: e,
10682
+ cache: this
10683
+ });
10684
+ let i = !1;
10685
+ if (this.#n !== 0) {
10686
+ let s = this.#s.get(e);
10687
+ if (s !== void 0) if (this.#g?.[s] && (clearTimeout(this.#g[s]), this.#g[s] = void 0), i = !0, this.#n === 1) this.#q(t);
10688
+ else {
10689
+ this.#x(s);
10690
+ let n = this.#t[s];
10691
+ if (this.#e(n) ? n.__abortController.abort(/* @__PURE__ */ new Error("deleted")) : (this.#T || this.#f) && (this.#T && this.#S?.(n, e, t), this.#f && this.#r?.push([
10692
+ n,
10693
+ e,
10694
+ t
10695
+ ])), this.#s.delete(e), this.#i[s] = void 0, this.#t[s] = void 0, s === this.#h) this.#h = this.#u[s];
10696
+ else if (s === this.#a) this.#a = this.#l[s];
10972
10697
  else {
10973
- this.#removeItemSize(index);
10974
- const v = this.#valList[index];
10975
- if (this.#isBackgroundFetch(v)) v.__abortController.abort(/* @__PURE__ */ new Error("deleted"));
10976
- else if (this.#hasDispose || this.#hasDisposeAfter) {
10977
- if (this.#hasDispose) this.#dispose?.(v, k, reason);
10978
- if (this.#hasDisposeAfter) this.#disposed?.push([
10979
- v,
10980
- k,
10981
- reason
10982
- ]);
10983
- }
10984
- this.#keyMap.delete(k);
10985
- this.#keyList[index] = void 0;
10986
- this.#valList[index] = void 0;
10987
- if (index === this.#tail) this.#tail = this.#prev[index];
10988
- else if (index === this.#head) this.#head = this.#next[index];
10989
- else {
10990
- const pi = this.#prev[index];
10991
- this.#next[pi] = this.#next[index];
10992
- const ni = this.#next[index];
10993
- this.#prev[ni] = this.#prev[index];
10994
- }
10995
- this.#size--;
10996
- this.#free.push(index);
10698
+ let o = this.#u[s];
10699
+ this.#l[o] = this.#l[s];
10700
+ let l = this.#l[s];
10701
+ this.#u[l] = this.#u[s];
10997
10702
  }
10703
+ this.#n--, this.#y.push(s);
10998
10704
  }
10999
10705
  }
11000
- if (this.#hasDisposeAfter && this.#disposed?.length) {
11001
- const dt = this.#disposed;
11002
- let task;
11003
- while (task = dt?.shift()) this.#disposeAfter?.(...task);
10706
+ if (this.#f && this.#r?.length) {
10707
+ let s = this.#r, n;
10708
+ for (; n = s?.shift();) this.#w?.(...n);
11004
10709
  }
11005
- return deleted;
10710
+ return i;
11006
10711
  }
11007
- /**
11008
- * Clear the cache entirely, throwing away all values.
11009
- */
11010
10712
  clear() {
11011
- return this.#clear("delete");
10713
+ return this.#q("delete");
11012
10714
  }
11013
- #clear(reason) {
11014
- for (const index of this.#rindexes({ allowStale: true })) {
11015
- const v = this.#valList[index];
11016
- if (this.#isBackgroundFetch(v)) v.__abortController.abort(/* @__PURE__ */ new Error("deleted"));
10715
+ #q(e) {
10716
+ for (let t of this.#z({ allowStale: !0 })) {
10717
+ let i = this.#t[t];
10718
+ if (this.#e(i)) i.__abortController.abort(/* @__PURE__ */ new Error("deleted"));
11017
10719
  else {
11018
- const k = this.#keyList[index];
11019
- if (this.#hasDispose) this.#dispose?.(v, k, reason);
11020
- if (this.#hasDisposeAfter) this.#disposed?.push([
11021
- v,
11022
- k,
11023
- reason
10720
+ let s = this.#i[t];
10721
+ this.#T && this.#S?.(i, s, e), this.#f && this.#r?.push([
10722
+ i,
10723
+ s,
10724
+ e
11024
10725
  ]);
11025
10726
  }
11026
10727
  }
11027
- this.#keyMap.clear();
11028
- this.#valList.fill(void 0);
11029
- this.#keyList.fill(void 0);
11030
- if (this.#ttls && this.#starts) {
11031
- this.#ttls.fill(0);
11032
- this.#starts.fill(0);
11033
- for (const t of this.#autopurgeTimers ?? []) if (t !== void 0) clearTimeout(t);
11034
- this.#autopurgeTimers?.fill(void 0);
10728
+ if (this.#s.clear(), this.#t.fill(void 0), this.#i.fill(void 0), this.#d && this.#F) {
10729
+ this.#d.fill(0), this.#F.fill(0);
10730
+ for (let t of this.#g ?? []) t !== void 0 && clearTimeout(t);
10731
+ this.#g?.fill(void 0);
11035
10732
  }
11036
- if (this.#sizes) this.#sizes.fill(0);
11037
- this.#head = 0;
11038
- this.#tail = 0;
11039
- this.#free.length = 0;
11040
- this.#calculatedSize = 0;
11041
- this.#size = 0;
11042
- if (this.#hasDisposeAfter && this.#disposed) {
11043
- const dt = this.#disposed;
11044
- let task;
11045
- while (task = dt?.shift()) this.#disposeAfter?.(...task);
10733
+ if (this.#_ && this.#_.fill(0), this.#a = 0, this.#h = 0, this.#y.length = 0, this.#b = 0, this.#n = 0, this.#f && this.#r) {
10734
+ let t = this.#r, i;
10735
+ for (; i = t?.shift();) this.#w?.(...i);
11046
10736
  }
11047
10737
  }
11048
10738
  };
11049
10739
  //#endregion
11050
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
10740
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
11051
10741
  /**
11052
10742
  * Unified memoised factory dispatching to the right provider flavour by the
11053
10743
  * source shape:
@@ -11070,7 +10760,7 @@ function ColumnsProvider(source) {
11070
10760
  * {@link AccessorColumnsProviderImpl}, so `indexAccessorRoot` runs once per
11071
10761
  * accessor root (within the LRU window).
11072
10762
  */
11073
- const _accessorProviderCache = new LRUCache({ max: 64 });
10763
+ const _accessorProviderCache = new U({ max: 64 });
11074
10764
  function AccessorColumnsProvider(root) {
11075
10765
  let provider = _accessorProviderCache.get(root.handle);
11076
10766
  if (provider === void 0) {
@@ -11084,7 +10774,7 @@ function AccessorColumnsProvider(root) {
11084
10774
  * {@link ResultPoolColumnsProviderImpl}, so `indexPoolBlock` runs once per
11085
10775
  * pool snapshot (within the LRU window).
11086
10776
  */
11087
- const _resultPoolProviderCache = new LRUCache({ max: 4 });
10777
+ const _resultPoolProviderCache = new U({ max: 4 });
11088
10778
  function ResultPoolColumnsProvider(rawPool = getCfgRenderCtx().getUpstreamBlockCtx()) {
11089
10779
  const key = hashRawPool(rawPool);
11090
10780
  let provider = _resultPoolProviderCache.get(key);
@@ -11136,7 +10826,7 @@ function hashRawPool(rawPool) {
11136
10826
  return rawPool.map((b) => `${b.blockId}\x1f${b.prodCtx ?? ""}\x1f${b.stagingCtx ?? ""}\x1f${b.prodIncomplete ? 1 : 0}\x1f${b.stagingIncomplete ? 1 : 0}`).join("");
11137
10827
  }
11138
10828
  //#endregion
11139
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
10829
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
11140
10830
  /**
11141
10831
  * Build the default set of ColumnsProviders for the ambient render ctx:
11142
10832
  * - `AccessorColumnsProvider` over `outputs` (if present)
@@ -11171,7 +10861,7 @@ function isColumnProvider(source) {
11171
10861
  return typeof p.getColumns === "function" && typeof p.isFinal === "function";
11172
10862
  }
11173
10863
  //#endregion
11174
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/data_column.js
10864
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/data_column.js
11175
10865
  /**
11176
10866
  * Thrown by leaf-recipe factories when the requested column is provably
11177
10867
  * absent in the active render ctx — i.e. every relevant accessor reports
@@ -11402,7 +11092,7 @@ const readDataStatus = memoizeByEntry(({ accessor, name }) => {
11402
11092
  return accessor.getInputsLocked() ? "absent" : "resolving";
11403
11093
  });
11404
11094
  function memoizeByEntry(fn) {
11405
- const cache = new LRUCache({ max: 1e3 });
11095
+ const cache = new U({ max: 1e3 });
11406
11096
  return (entry) => {
11407
11097
  const key = `${entry.accessor.handle}:${entry.name}`;
11408
11098
  let hit = cache.get(key);
@@ -11411,7 +11101,7 @@ function memoizeByEntry(fn) {
11411
11101
  };
11412
11102
  }
11413
11103
  //#endregion
11414
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
11104
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
11415
11105
  /**
11416
11106
  * Recipe wrapper that overlays {@link SpecOverrides} on top of any other
11417
11107
  * recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.
@@ -11549,7 +11239,7 @@ var DataColumnOverriddenRecipe = class extends ColumnOverriddenRecipe {
11549
11239
  }
11550
11240
  };
11551
11241
  //#endregion
11552
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
11242
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
11553
11243
  /**
11554
11244
  * Recipe wrapper that fixes the values of selected axes of an inner recipe
11555
11245
  * (axis slicing). The id is `FilteredPColumnId { source: inner.id,
@@ -11675,7 +11365,7 @@ function toAxisSelector(axis) {
11675
11365
  return selector;
11676
11366
  }
11677
11367
  //#endregion
11678
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
11368
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
11679
11369
  /**
11680
11370
  * Build a `ColumnRecipe` from a stringified id. Dispatches to the matching
11681
11371
  * concrete recipe variant based on the id's encoding and recurses on
@@ -11726,7 +11416,7 @@ function ColumnRecipeGetStatus(id, opts = {}) {
11726
11416
  }
11727
11417
  const ColumnRecipe = Object.assign(ColumnRecipeBuild, { getStatus: ColumnRecipeGetStatus });
11728
11418
  //#endregion
11729
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
11419
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
11730
11420
  /**
11731
11421
  * Recipe for columns identified by a {@link ColumnDiscoveredKey}: a base
11732
11422
  * column + a `path` of linkers + qualifications.
@@ -11897,7 +11587,7 @@ function referencedUniIdsOf(key) {
11897
11587
  return /* @__PURE__ */ new Set([key.column, ...(key.path ?? []).map((item) => item.column)]);
11898
11588
  }
11899
11589
  //#endregion
11900
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/column.js
11590
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/column.js
11901
11591
  /**
11902
11592
  * Unified entry point — routes between the two top-level dispatchers:
11903
11593
  * - string id (`PObjectId` / `ColumnUniversalId`) → {@link ColumnRecipe}
@@ -11911,7 +11601,7 @@ function Column(source, opts) {
11911
11601
  return DataColumn(source, opts);
11912
11602
  }
11913
11603
  //#endregion
11914
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11604
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11915
11605
  /**
11916
11606
  * Build a {@link ColumnsCollection} from sandbox-side source descriptors.
11917
11607
  * Resolves the `columnsCollection` driver (either from `deps.driver` or via
@@ -12020,7 +11710,35 @@ function defaultCtxSources(ctx) {
12020
11710
  return [...currentBlockSources(ctx), { kind: "result_pool" }];
12021
11711
  }
12022
11712
  //#endregion
12023
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/columns/utils.js
11713
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/peer_links.js
11714
+ /** Main axes of the datasets: the second axis of every column marked `pl7.app/isAnchor`. */
11715
+ function collectDatasetAxes(specs) {
11716
+ return new Set(specs.flatMap((spec) => {
11717
+ const main = spec.axesSpec[1];
11718
+ return readAnnotation(spec, Annotation.IsAnchor) === "true" && main !== void 0 ? [canonicalizeAxisId(main)] : [];
11719
+ }));
11720
+ }
11721
+ /** {@link collectDatasetAxes} over the result pool. */
11722
+ function getResultPoolDatasetAxes() {
11723
+ return collectDatasetAxes(ResultPoolColumnsProvider().getColumns().map((c) => c.getSpec()));
11724
+ }
11725
+ /**
11726
+ * Labels of the peer links on a linker path. A peer link joins two datasets' main axes, e.g. one
11727
+ * clonotype to another, so the columns behind it describe a different clonotype than the row.
11728
+ */
11729
+ function findPeerLinks(linkers, datasetAxes) {
11730
+ return uniq(linkers.flatMap((l) => {
11731
+ const peer = l.axesSpec.every((a) => datasetAxes.has(canonicalizeAxisId(a)));
11732
+ const label = readAnnotation(l, Annotation.LinkLabel) ?? readAnnotation(l, Annotation.Label);
11733
+ return peer && label ? [label] : [];
11734
+ }));
11735
+ }
11736
+ /** Hover text for the link icon. */
11737
+ function describePeerLinks(links) {
11738
+ return `Reached via ${links.join(", then ")}`;
11739
+ }
11740
+ //#endregion
11741
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/columns/utils.js
12024
11742
  /**
12025
11743
  * PObjectIds of every non-hit column referenced by `recipe.getQuery()`,
12026
11744
  * deduped in traversal order. The hit column is
@@ -12151,7 +11869,7 @@ function hasSingleDataColumn(recipe) {
12151
11869
  return recipe.getReferencedIds().length === 1;
12152
11870
  }
12153
11871
  //#endregion
12154
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
11872
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
12155
11873
  function getAllRelatedColumns(ctx, predicate) {
12156
11874
  const columns = new PColumnCollection();
12157
11875
  columns.addColumnProvider(ctx.resultPool);
@@ -12227,7 +11945,7 @@ function discoverIntegrableColumnIds(ctx, rootColumns) {
12227
11945
  }
12228
11946
  }
12229
11947
  //#endregion
12230
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
11948
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
12231
11949
  function isHiddenFromGraphColumn(column) {
12232
11950
  return !!readAnnotationJson(column, Annotation.HideDataFromGraphs);
12233
11951
  }
@@ -12256,7 +11974,169 @@ function createPFrameForGraphs(ctx, blockColumns) {
12256
11974
  }));
12257
11975
  }
12258
11976
  //#endregion
12259
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/filters/traverse.js
11977
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/filter_discovery.js
11978
+ /**
11979
+ * Matches columns annotated `pl7.app/isSubset: "true"` whose axes ⊆ anchor axes.
11980
+ *
11981
+ * Filter-intent: only the dataset's own direct subset columns, no linker
11982
+ * traversal — so this uses `.filter()` (pins `maxHops: 0`), not `.discover()`
11983
+ * (which would default to 4 hops and surface subset columns from other,
11984
+ * linker-reachable datasets). `.filter()` still applies the default
11985
+ * `enrichment` matching mode (`allowFloatingHitAxes: false`), which enforces
11986
+ * the axes-subset constraint. See `matchingModeToConstraints()`.
11987
+ */
11988
+ function findFilterColumns(options) {
11989
+ return ColumnsCollection([...options.sources], { driver: options.driver }).filter({
11990
+ anchors: { main: options.anchorSpec },
11991
+ include: { annotations: { [Annotation.IsSubset]: "true" } }
11992
+ }).getColumns();
11993
+ }
11994
+ /**
11995
+ * Derive labeled options from filter column variants, for use in DatasetOption.filters.
11996
+ *
11997
+ * Entries whose column id has no PlRef in `refsByObjectId` are silently
11998
+ * skipped — they cannot be exposed as user-selectable options.
11999
+ */
12000
+ function filterMatchesToOptions(variants, options) {
12001
+ if (variants.length === 0) return [];
12002
+ const { refsByObjectId, datasetSpec, labelOptions } = options;
12003
+ const entries = variants.flatMap((variant) => {
12004
+ const ref = refsByObjectId.get(extractPObjectId(variant.id));
12005
+ if (ref === void 0) return [];
12006
+ return [{
12007
+ ref,
12008
+ spec: variant.getSpec(),
12009
+ linkerPath: collectLinkerColumns(variant).map((linker) => ({ spec: linker.getSpec() }))
12010
+ }];
12011
+ });
12012
+ const labels = deriveDistinctLabels([...entries, { spec: datasetSpec }], {
12013
+ ...labelOptions,
12014
+ formatters: {
12015
+ ...labelOptions?.formatters,
12016
+ native: () => void 0
12017
+ }
12018
+ });
12019
+ return entries.map(({ ref }, i) => ({
12020
+ ref,
12021
+ label: labels[i]
12022
+ }));
12023
+ }
12024
+ /** Build the `refsByObjectId` map from `ctx.resultPool.getSpecs().entries`. */
12025
+ function buildRefMap(entries) {
12026
+ return new Map(entries.map((e) => [(0, import_canonicalize.default)(e.ref), e.ref]));
12027
+ }
12028
+ //#endregion
12029
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/enrichment_discovery.js
12030
+ /**
12031
+ * Linker-reached hits attached to the anchor primary. Drops zero-hop variants
12032
+ * (filters / the primary itself) and structural hits (subset, linker, label
12033
+ * columns). Narrow further with `include` selectors or a `predicate`.
12034
+ */
12035
+ function findEnrichmentColumns(options) {
12036
+ const include = options.include === void 0 ? void 0 : Array.isArray(options.include) ? options.include : [options.include];
12037
+ const columns = ColumnsCollection([...options.sources], { driver: options.driver }).discover({
12038
+ anchors: { main: options.anchorSpec },
12039
+ mode: "enrichment",
12040
+ maxHops: options.maxHops ?? 4,
12041
+ include,
12042
+ exclude: [
12043
+ { annotations: { [Annotation.IsSubset]: "true" } },
12044
+ { annotations: { [Annotation.IsLinkerColumn]: "true" } },
12045
+ { name: Annotation.Label }
12046
+ ]
12047
+ }).getColumns();
12048
+ const predicate = options.predicate;
12049
+ return columns.filter((v) => {
12050
+ if (hasSingleDataColumn(v)) return false;
12051
+ if (predicate !== void 0 && !predicate(v.getSpec())) return false;
12052
+ if (!isGlobalPObjectId(extractPObjectId(v.id))) return false;
12053
+ if (collectLinkerIds(v).some((id) => !isGlobalPObjectId(id))) return false;
12054
+ return true;
12055
+ });
12056
+ }
12057
+ /**
12058
+ * Pair each variant with a path-disambiguated label (so export headers stay
12059
+ * unique) and carry hit/linker `PObjectId`s through verbatim. Propagates
12060
+ * `qualifications.forHit`; `forQueries` is re-derived by the table builder.
12061
+ */
12062
+ function enrichmentVariantsToRefs(variants, labelOptions) {
12063
+ if (variants.length === 0) return [];
12064
+ const linkerIdsByVariant = variants.map((v) => collectLinkerIds(v));
12065
+ const hitQualsByVariant = variants.map((v) => [...hitQualifications(v)]);
12066
+ const labels = deriveDistinctLabels(variants.map((variant, i) => ({
12067
+ spec: variant.getSpec(),
12068
+ linkerPath: collectLinkerColumns(variant).map((linker) => ({ spec: linker.getSpec() })),
12069
+ qualifications: {
12070
+ forHit: hitQualsByVariant[i],
12071
+ forQueries: queriesQualifications(variant)
12072
+ }
12073
+ })), labelOptions);
12074
+ return variants.map((variant, i) => {
12075
+ const path = linkerIdsByVariant[i].length === 0 ? void 0 : linkerIdsByVariant[i].map((id) => ({
12076
+ type: "linker",
12077
+ linker: id
12078
+ }));
12079
+ return {
12080
+ ref: createEnrichmentRef(extractPObjectId(variant.id), {
12081
+ path,
12082
+ qualifications: hitQualsByVariant[i]
12083
+ }),
12084
+ label: labels[i]
12085
+ };
12086
+ });
12087
+ }
12088
+ //#endregion
12089
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PlDatasetSelector/build_dataset_options.js
12090
+ function toPredicate(opt) {
12091
+ if (opt === void 0) return () => true;
12092
+ return typeof opt === "function" ? opt : multiColumnSelectorsToPredicate(opt);
12093
+ }
12094
+ /**
12095
+ * Usage:
12096
+ * ```ts
12097
+ * .output("datasetOptions", (ctx) => buildDatasetOptions(ctx))
12098
+ * ```
12099
+ */
12100
+ function buildDatasetOptions(ctx, opts) {
12101
+ const primaryPredicate = toPredicate(opts?.primary);
12102
+ const filterPredicate = toPredicate(opts?.filter);
12103
+ const options = ctx.resultPool.getOptions(primaryPredicate, { refsWithEnrichments: opts?.requireEnrichments ?? true });
12104
+ if (options.length === 0) return [];
12105
+ const refMap = buildRefMap(ctx.resultPool.getSpecs().entries);
12106
+ const withEnrichments = opts?.withEnrichments ?? false;
12107
+ const filterSource = ColumnsProvider(ctx.ctx.getUpstreamBlockCtx());
12108
+ const enrichmentSources = withEnrichments ? getCtxProviders(ctx) : void 0;
12109
+ return options.map((primary) => {
12110
+ const datasetSpec = ctx.resultPool.getPColumnSpecByRef(primary.ref);
12111
+ if (!datasetSpec) return { primary };
12112
+ const filterMatches = findFilterColumns({
12113
+ sources: [filterSource],
12114
+ anchorSpec: datasetSpec
12115
+ }).filter((m) => filterPredicate(m.getSpec()));
12116
+ const filters = filterMatches.length === 0 ? void 0 : filterMatchesToOptions(filterMatches, {
12117
+ refsByObjectId: refMap,
12118
+ datasetSpec,
12119
+ labelOptions: opts?.labelOptions
12120
+ });
12121
+ let enrichments;
12122
+ if (enrichmentSources && withEnrichments) {
12123
+ const enrichmentVariants = findEnrichmentColumns({
12124
+ sources: enrichmentSources,
12125
+ anchorSpec: datasetSpec,
12126
+ maxHops: opts?.enrichmentMaxHops,
12127
+ ...typeof withEnrichments === "function" ? { predicate: withEnrichments } : { include: withEnrichments }
12128
+ });
12129
+ if (enrichmentVariants.length > 0) enrichments = enrichmentVariantsToRefs(enrichmentVariants, opts?.labelOptions);
12130
+ }
12131
+ return {
12132
+ primary,
12133
+ ...filters !== void 0 && filters.length > 0 ? { filters } : {},
12134
+ ...enrichments !== void 0 && enrichments.length > 0 ? { enrichments } : {}
12135
+ };
12136
+ });
12137
+ }
12138
+ //#endregion
12139
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/filters/traverse.js
12260
12140
  /**
12261
12141
  * Recursively traverses a FilterSpec tree bottom-up, applying visitor callbacks.
12262
12142
  *
@@ -12295,7 +12175,7 @@ function collectFilterSpecColumns(filter) {
12295
12175
  });
12296
12176
  }
12297
12177
  //#endregion
12298
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/filters/converters/filterToQuery.js
12178
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/filters/converters/filterToQuery.js
12299
12179
  /** Converts a QueryColumnId object into a SpecQueryExpression reference. */
12300
12180
  function resolveColumnRef(col) {
12301
12181
  return col.type === "axis" ? {
@@ -12607,7 +12487,7 @@ function isEmpty(value) {
12607
12487
  return true;
12608
12488
  }
12609
12489
  //#endregion
12610
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/filters/distill.js
12490
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/filters/distill.js
12611
12491
  /**
12612
12492
  * Strips non-FilterSpec metadata (whitelist approach) and removes
12613
12493
  * unfilled leaves (type is undefined or any required field is undefined).
@@ -12712,7 +12592,7 @@ const REQUIRED_KEYS_BY_TYPE = {
12712
12592
  greaterThanColumnOrEqual: ["column", "rhs"]
12713
12593
  };
12714
12594
  //#endregion
12715
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/state-migration.js
12595
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/state-migration.js
12716
12596
  /** Upgrade PlDataTableStateV2 to the latest version */
12717
12597
  function upgradePlDataTableStateV2(state) {
12718
12598
  if (!state) return createPlDataTableStateV2();
@@ -13070,7 +12950,7 @@ function parseLegacyLeafColumn(s) {
13070
12950
  return parsed;
13071
12951
  }
13072
12952
  //#endregion
13073
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/utils.js
12953
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/utils.js
13074
12954
  /** Adapt a {@link ColumnRecipe} to the plain {@link RuleColumn} shape. */
13075
12955
  function toRuleColumn(col) {
13076
12956
  return {
@@ -13164,11 +13044,12 @@ function deriveAllLabels(options) {
13164
13044
  return deriveDistinctLabels(columns.map((c) => ({
13165
13045
  spec: c.spec,
13166
13046
  linkerPath: c.linkerPath?.map((step) => ({ spec: step.linker.spec })),
13167
- qualifications: c.qualifications
13047
+ qualifications: c.qualifications,
13048
+ marker: c.marker
13168
13049
  })), deriveLabelsOptions).reduce((acc, label, index) => (acc[columns[index].id] = label, acc), {});
13169
13050
  }
13170
13051
  //#endregion
13171
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js
13052
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js
13172
13053
  /**
13173
13054
  * Assemble a ptable def directly from recipes. Each secondary recipe is its own
13174
13055
  * outer-joined subtree: `getQuery()` encodes its linker chain, and its
@@ -13232,7 +13113,7 @@ function columnToJoinEntry(col, qualifications) {
13232
13113
  };
13233
13114
  }
13234
13115
  //#endregion
13235
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/columnResolver.js
13116
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/columnResolver.js
13236
13117
  function createColumnResolver(columns) {
13237
13118
  const axisIds = [];
13238
13119
  for (const c of columns) for (const ax of c.getSpec().axesSpec) axisIds.push(getAxisId(ax));
@@ -13254,7 +13135,7 @@ function createColumnResolver(columns) {
13254
13135
  };
13255
13136
  }
13256
13137
  //#endregion
13257
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/discoverColumns.js
13138
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/discoverColumns.js
13258
13139
  /**
13259
13140
  * Discover columns from sources/anchors and split them into primary
13260
13141
  * (direct anchor hits — zero-hop, query is a bare column) and secondary
@@ -13300,7 +13181,7 @@ function discoverLabelColumns(ctx, primary) {
13300
13181
  }).getColumns();
13301
13182
  }
13302
13183
  //#endregion
13303
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.1/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js
13184
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.86.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js
13304
13185
  function createPlDataTableV3(ctx, options) {
13305
13186
  const state = upgradePlDataTableStateV2(options.tableState);
13306
13187
  const primaryJoinType = options.primaryJoinType ?? "full";
@@ -13309,8 +13190,13 @@ function createPlDataTableV3(ctx, options) {
13309
13190
  const { primary, secondary } = resolved;
13310
13191
  if (primary.length === 0) return void 0;
13311
13192
  const { direct, linked } = splitByTopology(secondary);
13193
+ const labelable = [...primary, ...secondary].map(toLabelableColumn);
13194
+ const linkHints = collectLinkHints(labelable);
13312
13195
  const derivedLabels = deriveAllLabels({
13313
- columns: [...primary, ...secondary].filter((c) => !isColumnHidden(c.getSpec())).map(toLabelableColumn),
13196
+ columns: labelable.filter((c) => !isColumnHidden(c.spec)).map((c) => ({
13197
+ ...c,
13198
+ marker: linkHints.get(c.id)
13199
+ })),
13314
13200
  deriveLabelsOptions: {
13315
13201
  includeNativeLabel: true,
13316
13202
  ...options.labelsOptions
@@ -13383,6 +13269,7 @@ function createPlDataTableV3(ctx, options) {
13383
13269
  ],
13384
13270
  primaryColumns: primary,
13385
13271
  derivedLabels,
13272
+ linkHints,
13386
13273
  visibilityByColId,
13387
13274
  orderByColId
13388
13275
  });
@@ -13424,6 +13311,15 @@ function splitByTopology(columns) {
13424
13311
  function collectLinkerSnapshots(linked) {
13425
13312
  return uniqueBy(linked.flatMap((c) => collectLinkerColumns(c)), (c) => c.id);
13426
13313
  }
13314
+ /** Link icon hover text per column, for columns reached through at least one peer link. */
13315
+ function collectLinkHints(columns) {
13316
+ if (!columns.some((c) => c.linkerPath?.length)) return /* @__PURE__ */ new Map();
13317
+ const datasetAxes = getResultPoolDatasetAxes();
13318
+ return new Map(columns.flatMap((c) => {
13319
+ const links = findPeerLinks(c.linkerPath?.map((step) => step.linker.spec) ?? [], datasetAxes);
13320
+ return links.length > 0 ? [[c.id, describePeerLinks(links)]] : [];
13321
+ }));
13322
+ }
13427
13323
  function toLabelableColumn(col) {
13428
13324
  return {
13429
13325
  id: col.id,
@@ -13444,7 +13340,7 @@ function toLabelableColumn(col) {
13444
13340
  * The UI overlays this onto the engine-emitted specs at render time.
13445
13341
  */
13446
13342
  function buildColumnsMeta(params) {
13447
- const { fullColumns, visibleColumns, primaryColumns, derivedLabels } = params;
13343
+ const { fullColumns, visibleColumns, primaryColumns, derivedLabels, linkHints } = params;
13448
13344
  const { visibilityByColId, orderByColId } = params;
13449
13345
  const visibleStatus = buildDataStatusMap(visibleColumns);
13450
13346
  const columns = fullColumns.reduce((acc, c) => {
@@ -13453,7 +13349,8 @@ function buildColumnsMeta(params) {
13453
13349
  label: derivedLabels[c.id],
13454
13350
  visibility: getEffectiveVisibility(rc, visibilityByColId),
13455
13351
  order: getOrderPriority(rc, orderByColId),
13456
- status: visibleStatus[c.id]
13352
+ status: visibleStatus[c.id],
13353
+ linkHint: linkHints.get(c.id)
13457
13354
  };
13458
13355
  return acc;
13459
13356
  }, {});
@@ -13663,6 +13560,11 @@ const ErrorShape = objectType({
13663
13560
  errors: lazyType(() => ErrorShape.array()).optional()
13664
13561
  });
13665
13562
  //#endregion
13563
+ //#region ../node_modules/.pnpm/es-toolkit@1.41.0/node_modules/es-toolkit/dist/predicate/isBoolean.mjs
13564
+ function isBoolean(x) {
13565
+ return typeof x === "boolean";
13566
+ }
13567
+ //#endregion
13666
13568
  //#region ../node_modules/.pnpm/es-toolkit@1.41.0/node_modules/es-toolkit/dist/predicate/isString.mjs
13667
13569
  function isString(value) {
13668
13570
  return typeof value === "string";
@@ -13675,6 +13577,30 @@ function isNumber(value) {
13675
13577
  //#endregion
13676
13578
  //#region ../kind/dist/index.js
13677
13579
  /**
13580
+ * The equations the block fits.
13581
+ *
13582
+ * `log_fluorescence` is a Hill fit on the log gate fluorescence with the exponent fixed at 1,
13583
+ * weighted least squares. `hill_gate_index` is the fit the block shipped through 2.4.0: a Hill
13584
+ * fit on the read-weighted mean gate index with a free exponent, graded on R² and the exponent.
13585
+ */
13586
+ const EQUATIONS = ["log_fluorescence", "hill_gate_index"];
13587
+ /**
13588
+ * How the error of a value combined over sample replicates is computed.
13589
+ *
13590
+ * `sd_over_sqrt_n` is the sample SD over the square root of the replicate count, falling back to
13591
+ * the single fit's own standard error for one replicate. `phillips` is the population SD over the
13592
+ * square root of the count plus one, which is 0 for one replicate; it reproduces the SEM published
13593
+ * with Phillips 2021.
13594
+ */
13595
+ const REPLICATE_ERROR_MODELS = ["sd_over_sqrt_n", "phillips"];
13596
+ const DEFAULT_REPLICATE_ERROR_MODEL = "sd_over_sqrt_n";
13597
+ /**
13598
+ * Share of the entered replicates one censoring side must hold, and exceed the other side by, for
13599
+ * the combined value to be reported as that side's bound. The block's own rule: no published
13600
+ * method defines one, and opposite bounds cannot be averaged into anything meaningful.
13601
+ */
13602
+ const DEFAULT_CENSORED_MAJORITY = .5;
13603
+ /**
13678
13604
  * The contract at runtime, for params arriving from a template file rather than typed code. An
13679
13605
  * absent field is always allowed — every param is optional and the block's own default takes
13680
13606
  * over — so each guard runs only on what is present. Keys the contract does not name are dropped
@@ -13716,6 +13642,14 @@ function isNumberFrom(min) {
13716
13642
  return (v) => isFiniteNumber(v) && v >= min;
13717
13643
  }
13718
13644
  const isFraction = (v) => isFiniteNumber(v) && v >= 0 && v <= 1;
13645
+ /** A fraction with zero excluded: a plateau floor of 0 asks for no rise at all. */
13646
+ const isPositiveFraction = (v) => isFiniteNumber(v) && v > 0 && v <= 1;
13647
+ const isEquation = (v) => isString(v) && EQUATIONS.includes(v);
13648
+ const isReplicateErrorModel = (v) => isString(v) && REPLICATE_ERROR_MODELS.includes(v);
13649
+ /** A positive number: a cutoff of 0 decades rejects every fit. */
13650
+ const isPositiveNumber = (v) => isFiniteNumber(v) && v > 0;
13651
+ /** A share from one half to the whole: below one half no side can be the majority. */
13652
+ const isMajority = (v) => isFiniteNumber(v) && v >= .5 && v <= 1;
13719
13653
  /**
13720
13654
  * The runtime half of the contract. The `satisfies` clause is what stops it drifting: every
13721
13655
  * field `BlockParams` declares must appear here, and each guard must narrow to that field's own
@@ -13728,11 +13662,18 @@ const isFraction = (v) => isFiniteNumber(v) && v >= 0 && v <= 1;
13728
13662
  */
13729
13663
  const CONTRACT = {
13730
13664
  abundanceRef: check(isPlRef, "a reference to an abundance column"),
13665
+ filterRef: check(isPlRef, "a reference to a subset column"),
13731
13666
  concentrationColumnRef: check(isPlRef, "a reference to a concentration column"),
13732
13667
  binColumnRef: check(isPlRef, "a reference to a FACS bin column"),
13733
13668
  antigenColumnRef: check(isPlRef, "a reference to an antigen column"),
13734
13669
  sortFractionColumnRef: check(isPlRef, "a reference to a FACS sort fraction column"),
13670
+ binFluorescenceColumnRef: check(isPlRef, "a reference to a gate fluorescence column"),
13735
13671
  targetAntigen: check(isString, "a string"),
13672
+ equation: check(isEquation, `one of ${EQUATIONS.map((e) => `"${e}"`).join(" or ")}`),
13673
+ plateauFloor: check(isPositiveFraction, "a number above 0 and at most 1"),
13674
+ r2GateMin: check(isFraction, "a number between 0 and 1"),
13675
+ requireAllConcentrations: check(isBoolean, "true or false"),
13676
+ kdSeGateMax: check((v) => isFiniteNumber(v) && v > 0, "a number above 0"),
13736
13677
  minReadsPerConcentration: check(isNumberFrom(1), "a number of 1 or more"),
13737
13678
  minConcentrationPoints: check(isNumberFrom(3), "a number of 3 or more"),
13738
13679
  r2ThresholdGood: check(isFraction, "a number between 0 and 1"),
@@ -13742,10 +13683,27 @@ const CONTRACT = {
13742
13683
  hookEffectThresholdBin: check(isFiniteNumber, "a number"),
13743
13684
  hookEffectThresholdNoBin: check(isFiniteNumber, "a number"),
13744
13685
  hookEffectMinReads: check(isFiniteNumber, "a number"),
13686
+ replicateColumnRef: check(isPlRef, "a reference to a replicate column"),
13687
+ replicateErrorModel: check(isReplicateErrorModel, `one of ${REPLICATE_ERROR_MODELS.map((m) => `"${m}"`).join(" or ")}`),
13688
+ replicateFitErrorCutoff: check(isPositiveNumber, "a number above 0"),
13689
+ replicateR2Floor: check(isFraction, "a number between 0 and 1"),
13690
+ replicateCensoredMajority: check(isMajority, "a number between 0.5 and 1"),
13745
13691
  customBlockLabel: check(isString, "a string")
13746
13692
  };
13693
+ Object.keys(CONTRACT);
13747
13694
  //#endregion
13748
13695
  //#region ../model/dist/index.js
13696
+ /**
13697
+ * The per-replicate chart: one dot per replicate on a log Kd,app axis. The page binds the sources
13698
+ * from the columns the run produced.
13699
+ */
13700
+ const REPLICATES_DEFAULT_STATE = {
13701
+ title: "",
13702
+ template: "dots",
13703
+ currentTab: null,
13704
+ layersSettings: { dots: {} },
13705
+ axesSettings: { axisY: { scale: "log" } }
13706
+ };
13749
13707
  const summaryCol = (name, type) => `{"kind":"column","name":"{\\"name\\":\\"${name}\\",\\"resolvePath\\":[\\"main\\",\\"summaryPf\\"]}","type":"${type}"}`;
13750
13708
  const KD_PLOT_COL = summaryCol("kdPlotPosition", "Double");
13751
13709
  const HILL_PLOT_COL = summaryCol("hillPlotPosition", "Double");
@@ -13760,7 +13718,10 @@ const AFFINITY_VS_FIT_DEFAULT_STATE = {
13760
13718
  type: "grouping",
13761
13719
  value: FIT_FAILURE_REASON_COL
13762
13720
  } } },
13763
- axesSettings: { axisX: { scale: "log" } },
13721
+ axesSettings: {
13722
+ axisX: { scale: "log" },
13723
+ axisY: { scale: "log" }
13724
+ },
13764
13725
  optionsState: {
13765
13726
  type: "scatterplot",
13766
13727
  components: {
@@ -13828,20 +13789,34 @@ const AFFINITY_VS_FIT_DEFAULT_STATE = {
13828
13789
  */
13829
13790
  const initBlockData = (params) => ({
13830
13791
  abundanceRef: params?.abundanceRef,
13792
+ filterRef: params?.filterRef,
13831
13793
  concentrationColumnRef: params?.concentrationColumnRef,
13832
13794
  binColumnRef: params?.binColumnRef,
13795
+ binFluorescenceColumnRef: params?.binFluorescenceColumnRef,
13833
13796
  antigenColumnRef: params?.antigenColumnRef,
13834
13797
  sortFractionColumnRef: params?.sortFractionColumnRef,
13835
13798
  targetAntigen: params?.targetAntigen,
13836
- minReadsPerConcentration: params?.minReadsPerConcentration ?? 3,
13837
- minConcentrationPoints: params?.minConcentrationPoints ?? 5,
13838
- r2ThresholdGood: params?.r2ThresholdGood ?? .8,
13839
- r2ThresholdFailed: params?.r2ThresholdFailed ?? .5,
13840
- nMin: params?.nMin ?? .5,
13841
- nMax: params?.nMax ?? 2,
13842
- hookEffectThresholdBin: params?.hookEffectThresholdBin ?? .2,
13843
- hookEffectThresholdNoBin: params?.hookEffectThresholdNoBin ?? .02,
13844
- hookEffectMinReads: params?.hookEffectMinReads ?? 20,
13799
+ equation: params?.equation ?? (params?.minReadsPerConcentration !== void 0 ? "hill_gate_index" : "log_fluorescence"),
13800
+ plateauFloor: params?.plateauFloor ?? .667,
13801
+ r2GateMin: params?.r2GateMin ?? .8,
13802
+ kdSeGateMax: params?.kdSeGateMax ?? 1,
13803
+ requireAllConcentrations: params?.requireAllConcentrations,
13804
+ replicateColumnRef: params?.replicateColumnRef,
13805
+ replicateErrorModel: params?.replicateErrorModel ?? "sd_over_sqrt_n",
13806
+ replicateFitErrorCutoff: params?.replicateFitErrorCutoff,
13807
+ replicateR2Floor: params?.replicateR2Floor,
13808
+ replicateCensoredMajority: params?.replicateCensoredMajority ?? .5,
13809
+ replicateTableState: createPlDataTableStateV2(),
13810
+ graphStateReplicates: REPLICATES_DEFAULT_STATE,
13811
+ minReadsPerConcentration: params?.minReadsPerConcentration ?? READ_COVERAGE_DEFAULTS.minReadsPerConcentration,
13812
+ minConcentrationPoints: params?.minConcentrationPoints ?? READ_COVERAGE_DEFAULTS.minConcentrationPoints,
13813
+ r2ThresholdGood: params?.r2ThresholdGood ?? HILL_GATE_INDEX_DEFAULTS.r2ThresholdGood,
13814
+ r2ThresholdFailed: params?.r2ThresholdFailed ?? HILL_GATE_INDEX_DEFAULTS.r2ThresholdFailed,
13815
+ nMin: params?.nMin ?? HILL_GATE_INDEX_DEFAULTS.nMin,
13816
+ nMax: params?.nMax ?? HILL_GATE_INDEX_DEFAULTS.nMax,
13817
+ hookEffectThresholdBin: params?.hookEffectThresholdBin ?? HILL_GATE_INDEX_DEFAULTS.hookEffectThresholdBin,
13818
+ hookEffectThresholdNoBin: params?.hookEffectThresholdNoBin ?? HILL_GATE_INDEX_DEFAULTS.hookEffectThresholdNoBin,
13819
+ hookEffectMinReads: params?.hookEffectMinReads ?? HILL_GATE_INDEX_DEFAULTS.hookEffectMinReads,
13845
13820
  defaultBlockLabel: "Tite-Seq Analysis",
13846
13821
  customBlockLabel: params?.customBlockLabel ?? "",
13847
13822
  tableState: createPlDataTableStateV2(),
@@ -13866,7 +13841,91 @@ const initBlockData = (params) => ({
13866
13841
  graphStateAffinityVsFit: AFFINITY_VS_FIT_DEFAULT_STATE,
13867
13842
  settingsOpen: false
13868
13843
  });
13869
- const dataModel = new DataModelBuilder({ kind }).from("v1").init(({ params }) => initBlockData(params));
13844
+ /**
13845
+ * v1 -> v2. A v1 project (v2.4.0 or earlier) ran the gate-index fit, so name it.
13846
+ *
13847
+ * Writing the field is the point. An absent `equation` reads as a new block's default,
13848
+ * `log_fluorescence`, and every released project would change the equation it fits.
13849
+ *
13850
+ * The plateau floor arrives at a new block's value and stays unread. `hill_gate_index` does
13851
+ * not read one. Nothing else moves: every setting, reference, label and piece of view state
13852
+ * crosses untouched, so a re-run reproduces the numbers the project already holds.
13853
+ */
13854
+ const migrateV1ToV2 = (v1) => ({
13855
+ ...v1,
13856
+ equation: "hill_gate_index",
13857
+ plateauFloor: DEFAULT_PLATEAU_FLOOR
13858
+ });
13859
+ /**
13860
+ * v2 -> v3. The R² gate arrives off, so a log-fluorescence project rates its fits as it did. v2
13861
+ * shipped only in development builds; the step repairs their stored projects.
13862
+ */
13863
+ const migrateV2ToV3 = (v2) => ({
13864
+ ...v2,
13865
+ r2GateEnabled: false,
13866
+ r2GateMin: .8
13867
+ });
13868
+ /**
13869
+ * v3 -> v4. Sample replicates arrive unset: no replicate column, both filters off, the default
13870
+ * error model and censoring majority, and empty per-replicate view state. The args a v3 project
13871
+ * sends do not move, so it does not re-run.
13872
+ */
13873
+ const migrateV3ToV4 = (v3) => ({
13874
+ ...v3,
13875
+ replicateErrorModel: DEFAULT_REPLICATE_ERROR_MODEL,
13876
+ replicateCensoredMajority: DEFAULT_CENSORED_MAJORITY,
13877
+ replicateTableState: createPlDataTableStateV2(),
13878
+ graphStateReplicates: REPLICATES_DEFAULT_STATE
13879
+ });
13880
+ /**
13881
+ * v4 -> v5. A stored point count below the minimum is raised to it. A cleared field stays cleared.
13882
+ * Raising it changes that project's args, so the block goes stale.
13883
+ */
13884
+ const migrateV4ToV5 = (v4) => ({
13885
+ ...v4,
13886
+ minConcentrationPoints: v4.minConcentrationPoints === void 0 ? void 0 : Math.max(v4.minConcentrationPoints, 5)
13887
+ });
13888
+ /**
13889
+ * v5 -> v6. The checkbox is gone: a limit applies when it is set. A project with the checkbox off
13890
+ * clears both limits, and one with it on keeps them, so the args do not move and it does not
13891
+ * re-run.
13892
+ */
13893
+ const migrateV5ToV6 = ({ r2GateEnabled, ...v5 }) => ({
13894
+ ...v5,
13895
+ r2GateMin: r2GateEnabled ? v5.r2GateMin : void 0,
13896
+ kdSeGateMax: r2GateEnabled ? v5.kdSeGateMax : void 0
13897
+ });
13898
+ const dataModel = new DataModelBuilder({ kind }).from("v1").migrate("v2", migrateV1ToV2).migrate("v3", migrateV2ToV3).migrate("v4", migrateV3ToV4).migrate("v5", migrateV4ToV5).migrate("v6", migrateV5ToV6).init(({ params }) => initBlockData(params));
13899
+ /** The per-replicate frame of the last run. Undefined when the run combined no replicates. */
13900
+ function replicateCols(ctx) {
13901
+ return ctx.outputs?.resolve({
13902
+ field: "replicatePf",
13903
+ allowPermanentAbsence: true
13904
+ })?.getPColumns();
13905
+ }
13906
+ const REPLICATE_AXIS = "pl7.app/vdj/replicate";
13907
+ /**
13908
+ * The filter that narrows the per-replicate frame to one variant. The variant axis is whichever
13909
+ * axis is not the replicate one, taken from the frame's own spec so the domain matches exactly.
13910
+ * Undefined when nothing is selected or the frame has no such axis.
13911
+ */
13912
+ function replicateDrilldownFilter(specs, key) {
13913
+ const value = key?.[0];
13914
+ if (value === void 0 || value === null) return void 0;
13915
+ const axis = specs.find((s) => s.name === "pl7.app/vdj/kd")?.axesSpec.find((a) => a.name !== REPLICATE_AXIS);
13916
+ if (axis === void 0) return void 0;
13917
+ return {
13918
+ type: "and",
13919
+ filters: [{
13920
+ type: "patternEquals",
13921
+ column: {
13922
+ type: "axis",
13923
+ id: getAxisId(axis)
13924
+ },
13925
+ value: String(value)
13926
+ }]
13927
+ };
13928
+ }
13870
13929
  function isIntegerValueType(vt) {
13871
13930
  return vt === "Int" || vt === "Long";
13872
13931
  }
@@ -13891,16 +13950,86 @@ function filterPopulatedOptions(ctx, specPred, opts = {}) {
13891
13950
  return opts.valuePredicate ? opts.valuePredicate(finite) : true;
13892
13951
  });
13893
13952
  }
13894
- const platforma$1 = BlockModelV3.create({
13895
- dataModel,
13896
- kind
13897
- }).templateParams(deriveTemplateParams).args((data) => {
13953
+ const DATASET_KEY_AXES = /* @__PURE__ */ new Set([
13954
+ "pl7.app/vdj/clonotypeKey",
13955
+ "pl7.app/vdj/scClonotypeKey",
13956
+ "pl7.app/variantKey"
13957
+ ]);
13958
+ /**
13959
+ * The block's workflow input, and the gate on whether it may run at all: a throw here marks the
13960
+ * args invalid and disables Run. Named rather than written inline so the staleness contract —
13961
+ * which bytes a given state projects — can be asserted in a test.
13962
+ */
13963
+ const deriveArgs = (data) => {
13898
13964
  if (data.abundanceRef === void 0) throw new Error("Abundance column is required");
13899
13965
  if (data.concentrationColumnRef === void 0) throw new Error("Concentration column is required");
13900
13966
  if (data.antigenColumnRef !== void 0 && !data.targetAntigen) throw new Error("Target antigen is required when an antigen column is selected");
13901
13967
  if (data.sortFractionColumnRef !== void 0 && data.binColumnRef === void 0) throw new Error("FACS sort fraction requires a FACS bin column — the correction only applies in bin mode");
13968
+ const inputs = {
13969
+ abundanceRef: data.abundanceRef,
13970
+ concentrationColumnRef: data.concentrationColumnRef,
13971
+ binColumnRef: data.binColumnRef,
13972
+ antigenColumnRef: data.antigenColumnRef,
13973
+ sortFractionColumnRef: data.sortFractionColumnRef,
13974
+ targetAntigen: data.targetAntigen
13975
+ };
13976
+ if (data.replicateColumnRef !== void 0) {
13977
+ if (data.replicateFitErrorCutoff !== void 0 && data.replicateFitErrorCutoff <= 0) throw new Error("Replicate fit-error cutoff must be above 0, or empty to turn it off");
13978
+ if (data.replicateR2Floor !== void 0 && (data.replicateR2Floor < 0 || data.replicateR2Floor > 1)) throw new Error("Replicate R² floor must be between 0 and 1, or empty to turn it off");
13979
+ if (data.replicateCensoredMajority === void 0) throw new Error("Replicate censoring majority is required");
13980
+ if (data.replicateCensoredMajority < .5 || data.replicateCensoredMajority > 1) throw new Error("Replicate censoring majority must be between 0.5 and 1");
13981
+ }
13982
+ const labels = {
13983
+ defaultBlockLabel: data.defaultBlockLabel ?? "Tite-Seq Analysis",
13984
+ customBlockLabel: data.customBlockLabel ?? "",
13985
+ ...data.filterRef !== void 0 && { inputFilter: createGlobalPObjectId(data.filterRef.blockId, data.filterRef.name) },
13986
+ ...data.replicateColumnRef !== void 0 && {
13987
+ replicateColumnRef: data.replicateColumnRef,
13988
+ replicateErrorModel: "sd_over_sqrt_n",
13989
+ ...data.equation === "log_fluorescence" && data.replicateFitErrorCutoff !== void 0 && { replicateFitErrorCutoff: data.replicateFitErrorCutoff },
13990
+ ...data.replicateR2Floor !== void 0 && { replicateR2Floor: data.replicateR2Floor },
13991
+ replicateCensoredMajority: data.replicateCensoredMajority
13992
+ }
13993
+ };
13994
+ switch (data.equation) {
13995
+ case "log_fluorescence": return logFluorescenceArgs(data, inputs, labels);
13996
+ case "hill_gate_index": return hillGateIndexArgs(data, inputs, labels);
13997
+ default: throw new Error(`Unknown equation: ${data.equation}`);
13998
+ }
13999
+ };
14000
+ /**
14001
+ * Read coverage, which both equations read: a point below the read floor is dropped, and a
14002
+ * clonotype left with fewer than the point count is refused before any fit. Narrowed here because
14003
+ * a check in the caller does not narrow `data` inside each equation's builder.
14004
+ */
14005
+ function readCoverage(data) {
13902
14006
  if (data.minReadsPerConcentration === void 0) throw new Error("Min reads per concentration is required");
13903
14007
  if (data.minConcentrationPoints === void 0) throw new Error("Min concentration points is required");
14008
+ if (data.minReadsPerConcentration < 1) throw new Error("Min reads per concentration must be ≥ 1");
14009
+ if (data.minConcentrationPoints < 5) throw new Error(`Min concentration points must be ≥ 5`);
14010
+ return {
14011
+ minReadsPerConcentration: data.minReadsPerConcentration,
14012
+ minConcentrationPoints: data.minConcentrationPoints
14013
+ };
14014
+ }
14015
+ function logFluorescenceArgs(data, inputs, labels) {
14016
+ if (data.plateauFloor === void 0) throw new Error("Plateau floor is required");
14017
+ if (data.plateauFloor <= 0 || data.plateauFloor > 1) throw new Error("Plateau floor must be above 0 and at most 1");
14018
+ if (data.binColumnRef === void 0) throw new Error("The log fluorescence fit requires a FACS bin column. For frequency-only data, choose the Mean bin fit in Fit method equation.");
14019
+ if (data.r2GateMin !== void 0 && !(data.r2GateMin >= 0 && data.r2GateMin <= 1)) throw new Error("Minimum R² must be between 0 and 1, or empty for no limit");
14020
+ if (data.kdSeGateMax !== void 0 && !(data.kdSeGateMax > 0)) throw new Error("Maximum Kd,app SE must be above 0, or empty for no limit");
14021
+ return {
14022
+ ...inputs,
14023
+ binFluorescenceColumnRef: data.binFluorescenceColumnRef,
14024
+ equation: "log_fluorescence",
14025
+ plateauFloor: data.plateauFloor,
14026
+ ...readCoverage(data),
14027
+ ...data.r2GateMin !== void 0 && { r2GateMin: data.r2GateMin },
14028
+ ...data.kdSeGateMax !== void 0 && { kdSeGateMax: data.kdSeGateMax },
14029
+ ...labels
14030
+ };
14031
+ }
14032
+ function hillGateIndexArgs(data, inputs, labels) {
13904
14033
  if (data.r2ThresholdGood === void 0) throw new Error("R² threshold (Good) is required");
13905
14034
  if (data.r2ThresholdFailed === void 0) throw new Error("R² threshold (Failed) is required");
13906
14035
  if (data.nMin === void 0) throw new Error("Hill coefficient nMin is required");
@@ -13913,44 +14042,62 @@ const platforma$1 = BlockModelV3.create({
13913
14042
  if (data.nMin >= data.nMax) throw new Error("Hill coefficient nMin must be < nMax");
13914
14043
  if (data.r2ThresholdGood < 0 || data.r2ThresholdGood > 1) throw new Error("R² threshold (Good) out of range");
13915
14044
  if (data.r2ThresholdFailed < 0 || data.r2ThresholdFailed > 1) throw new Error("R² threshold (Failed) out of range");
13916
- if (data.minReadsPerConcentration < 1) throw new Error("Min reads per concentration must be ≥ 1");
13917
- if (data.minConcentrationPoints < 3) throw new Error("Min concentration points must be ≥ 3");
13918
14045
  return {
13919
- abundanceRef: data.abundanceRef,
13920
- concentrationColumnRef: data.concentrationColumnRef,
13921
- binColumnRef: data.binColumnRef,
13922
- antigenColumnRef: data.antigenColumnRef,
13923
- sortFractionColumnRef: data.sortFractionColumnRef,
13924
- targetAntigen: data.targetAntigen,
13925
- minReadsPerConcentration: data.minReadsPerConcentration,
13926
- minConcentrationPoints: data.minConcentrationPoints,
14046
+ ...inputs,
14047
+ ...readCoverage(data),
13927
14048
  r2ThresholdGood: data.r2ThresholdGood,
13928
14049
  r2ThresholdFailed: data.r2ThresholdFailed,
13929
14050
  nMin: data.nMin,
13930
14051
  nMax: data.nMax,
13931
- hookEffectThresholdBin: data.hookEffectThresholdBin ?? .2,
13932
- hookEffectThresholdNoBin: data.hookEffectThresholdNoBin ?? .02,
14052
+ hookEffectThresholdBin: data.hookEffectThresholdBin ?? HILL_GATE_INDEX_DEFAULTS.hookEffectThresholdBin,
14053
+ hookEffectThresholdNoBin: data.hookEffectThresholdNoBin ?? HILL_GATE_INDEX_DEFAULTS.hookEffectThresholdNoBin,
13933
14054
  hookEffectMinReads: data.hookEffectMinReads,
13934
- defaultBlockLabel: data.defaultBlockLabel ?? "Tite-Seq Analysis",
13935
- customBlockLabel: data.customBlockLabel ?? ""
14055
+ ...labels
13936
14056
  };
13937
- }).output("abundanceOptions", (ctx) => ctx.resultPool.getOptions([
14057
+ }
14058
+ /** The block's pages. Per-replicate values are read by clicking a variant in the main table. */
14059
+ const sectionsFor = () => [
13938
14060
  {
13939
- axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/vdj/clonotypeKey" }],
13940
- annotations: { "pl7.app/isAnchor": "true" }
14061
+ type: "link",
14062
+ href: "/",
14063
+ label: "Table"
14064
+ },
14065
+ {
14066
+ type: "link",
14067
+ href: "/titration-curves",
14068
+ label: "Titration Curves"
13941
14069
  },
13942
14070
  {
13943
- axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/vdj/scClonotypeKey" }],
13944
- annotations: { "pl7.app/isAnchor": "true" }
14071
+ type: "link",
14072
+ href: "/kd-distribution",
14073
+ label: "Kd Distribution"
13945
14074
  },
13946
14075
  {
13947
- axes: [{ name: "pl7.app/sampleId" }, { name: "pl7.app/variantKey" }],
13948
- annotations: { "pl7.app/isAnchor": "true" }
14076
+ type: "link",
14077
+ href: "/affinity-vs-fit",
14078
+ label: "Affinity vs Fit Quality"
13949
14079
  }
13950
- ], { label: { includeNativeLabel: false } })).output("concentrationOptions", (ctx) => filterPopulatedOptions(ctx, (spec) => isPColumnSpec(spec) && isFloatValueType(spec.valueType) && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId", { excludeRef: ctx.data.sortFractionColumnRef })).output("binOptions", (ctx) => filterPopulatedOptions(ctx, (spec) => isPColumnSpec(spec) && isIntegerValueType(spec.valueType) && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId")).output("sortFractionOptions", (ctx) => filterPopulatedOptions(ctx, (spec) => isPColumnSpec(spec) && isFloatValueType(spec.valueType) && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId", {
14080
+ ];
14081
+ const platforma$1 = BlockModelV3.create({
14082
+ dataModel,
14083
+ kind
14084
+ }).templateParams(deriveTemplateParams).args(deriveArgs).output("abundanceOptions", (ctx) => buildDatasetOptions(ctx, {
14085
+ primary: (spec) => isPColumnSpec(spec) && spec.annotations?.["pl7.app/isAnchor"] === "true" && spec.axesSpec.length === 2 && spec.axesSpec[0].name === "pl7.app/sampleId" && DATASET_KEY_AXES.has(spec.axesSpec[1].name),
14086
+ filter: (spec) => isPColumnSpec(spec) && spec.axesSpec.length === 1 && DATASET_KEY_AXES.has(spec.axesSpec[0].name),
14087
+ requireEnrichments: false
14088
+ }) ?? []).output("concentrationOptions", (ctx) => filterPopulatedOptions(ctx, (spec) => isPColumnSpec(spec) && isFloatValueType(spec.valueType) && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId", { excludeRef: ctx.data.sortFractionColumnRef })).output("binOptions", (ctx) => filterPopulatedOptions(ctx, (spec) => isPColumnSpec(spec) && isIntegerValueType(spec.valueType) && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId")).output("binFluorescenceOptions", (ctx) => filterPopulatedOptions(ctx, (spec) => isPColumnSpec(spec) && isFloatValueType(spec.valueType) && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId", { excludeRef: ctx.data.concentrationColumnRef })).output("sortFractionOptions", (ctx) => filterPopulatedOptions(ctx, (spec) => isPColumnSpec(spec) && isFloatValueType(spec.valueType) && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId", {
13951
14089
  excludeRef: ctx.data.concentrationColumnRef,
13952
14090
  valuePredicate: (finite) => finite.every((v) => v >= 0 && v <= 1)
13953
- })).output("antigenOptions", (ctx) => ctx.resultPool.getOptions((spec) => isPColumnSpec(spec) && spec.valueType === "String" && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId")).output("targetAntigenValues", (ctx) => {
14091
+ })).output("antigenOptions", (ctx) => ctx.resultPool.getOptions((spec) => isPColumnSpec(spec) && spec.valueType === "String" && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId")).output("replicateOptions", (ctx) => {
14092
+ const picked = [
14093
+ ctx.data.concentrationColumnRef,
14094
+ ctx.data.binColumnRef,
14095
+ ctx.data.sortFractionColumnRef,
14096
+ ctx.data.binFluorescenceColumnRef,
14097
+ ctx.data.antigenColumnRef
14098
+ ].filter((ref) => ref !== void 0);
14099
+ return filterPopulatedOptions(ctx, (spec) => isPColumnSpec(spec) && (spec.valueType === "String" || isIntegerValueType(spec.valueType)) && spec.axesSpec.length === 1 && spec.axesSpec[0].name === "pl7.app/sampleId").filter((opt) => !picked.some((ref) => plRefsEqual(opt.ref, ref)));
14100
+ }).output("targetAntigenValues", (ctx) => {
13954
14101
  if (!ctx.data.antigenColumnRef) return void 0;
13955
14102
  const values = (ctx.resultPool.getDataByRef(ctx.data.antigenColumnRef)?.data)?.getDataAsJson()?.["data"];
13956
14103
  if (!values) return void 0;
@@ -13964,9 +14111,13 @@ const platforma$1 = BlockModelV3.create({
13964
14111
  for (const key of [
13965
14112
  "summaryPf",
13966
14113
  "signalPf",
13967
- "logHandle"
14114
+ "logHandle",
14115
+ "replicatePf"
13968
14116
  ]) {
13969
- const errorAcc = ctx.outputs?.resolve(key)?.getError();
14117
+ const errorAcc = (key === "replicatePf" ? ctx.outputs?.resolve({
14118
+ field: key,
14119
+ allowPermanentAbsence: true
14120
+ }) : ctx.outputs?.resolve(key))?.getError();
13970
14121
  if (!errorAcc) continue;
13971
14122
  const typeName = errorAcc.resourceType.name;
13972
14123
  const detail = errorAcc.getDataAsJson()?.message ?? typeName;
@@ -13976,13 +14127,6 @@ const platforma$1 = BlockModelV3.create({
13976
14127
  message: isCidConflict ? `Transient result-hash conflict on "${key}": ${detail}. The platform retries automatically; usually self-recovers. If this persists across retries, the workflow likely has a non-deterministic step — report it.` : `Workflow output "${key}" failed: ${detail}`
13977
14128
  });
13978
14129
  }
13979
- if (data.concentrationColumnRef !== void 0) {
13980
- const unitLabel = ctx.resultPool.getPColumnSpecByRef(data.concentrationColumnRef)?.annotations?.["pl7.app/label"];
13981
- if (unitLabel && /\s/.test(unitLabel)) issues.push({
13982
- severity: "warning",
13983
- message: `Concentration column label "${unitLabel}" contains spaces. The full label becomes the Kd,app unit, so values render as "Kd,app (${unitLabel})". Use a bare unit like "nM" or "µM".`
13984
- });
13985
- }
13986
14130
  if (data.antigenColumnRef === void 0 && data.targetAntigen) issues.push({
13987
14131
  severity: "warning",
13988
14132
  message: "targetAntigen is set but no antigen column is selected — the value is ignored. Select an antigen column or clear the targetAntigen field."
@@ -13995,7 +14139,6 @@ const platforma$1 = BlockModelV3.create({
13995
14139
  }).output("logHandle", (ctx) => ctx.outputs?.resolve("logHandle")?.getLogHandle()).output("isRunning", (ctx) => ctx.outputs?.getIsReadyOrError() === false).outputWithStatus("summaryTable", (ctx) => {
13996
14140
  const summaryCols = ctx.outputs?.resolve("summaryPf")?.getPColumns();
13997
14141
  if (summaryCols === void 0) return void 0;
13998
- const signalCols = ctx.outputs?.resolve("signalPf")?.getPColumns() ?? [];
13999
14142
  const kdCol = summaryCols.find((c) => c.spec.name === "pl7.app/vdj/kd");
14000
14143
  if (!kdCol) return void 0;
14001
14144
  const resultPoolCols = ColumnsCollection(["result_pool"], { ctx: ctx.ctx }).filter({
@@ -14012,13 +14155,9 @@ const platforma$1 = BlockModelV3.create({
14012
14155
  return spec.valueType !== "File" && !spec.annotations?.["pl7.app/trace"]?.includes("milaboratories.titeseq-analysis");
14013
14156
  }).map((c) => c.withSpecs({ annotations: { "pl7.app/table/visibility": "optional" } }));
14014
14157
  return createPlDataTableV3(ctx, {
14015
- primaryColumns: [...summaryCols, ...signalCols].map((c) => DataColumn.fromColumn(c)),
14158
+ primaryColumns: summaryCols.map((c) => DataColumn.fromColumn(c)),
14016
14159
  columns: resultPoolCols,
14017
- tableState: ctx.data.tableState,
14018
- displayOptions: { visibility: [{
14019
- match: { name: [exactly("pl7.app/vdj/fitFailureReason"), ...signalCols.map((c) => exactly(c.spec.name))] },
14020
- visibility: "default"
14021
- }] }
14160
+ tableState: ctx.data.tableState
14022
14161
  });
14023
14162
  }).outputWithStatus("titrationCurvesPf", (ctx) => {
14024
14163
  const signalCols = ctx.outputs?.resolve("signalPf")?.getPColumns();
@@ -14048,28 +14187,52 @@ const platforma$1 = BlockModelV3.create({
14048
14187
  const pCols = ctx.outputs?.resolve("summaryPf")?.getPColumns();
14049
14188
  if (pCols === void 0) return void 0;
14050
14189
  return pCols.length === 0;
14051
- }).output("binMode", (ctx) => ctx.data.binColumnRef !== void 0).title(() => "Tite-Seq Analysis").subtitle((ctx) => ctx.data.customBlockLabel || ctx.data.defaultBlockLabel || "").sections((_ctx) => [
14052
- {
14053
- type: "link",
14054
- href: "/",
14055
- label: "Table"
14056
- },
14057
- {
14058
- type: "link",
14059
- href: "/titration-curves",
14060
- label: "Titration Curves"
14061
- },
14062
- {
14063
- type: "link",
14064
- href: "/kd-distribution",
14065
- label: "Kd Distribution"
14066
- },
14067
- {
14068
- type: "link",
14069
- href: "/affinity-vs-fit",
14070
- label: "Affinity vs Fit Quality"
14071
- }
14072
- ]).done();
14190
+ }).output("binMode", (ctx) => ctx.data.binColumnRef !== void 0).output("replicates", (ctx) => replicateCols(ctx) !== void 0).outputWithStatus("replicateTable", (ctx) => {
14191
+ const cols = replicateCols(ctx);
14192
+ if (cols === void 0) return void 0;
14193
+ return createPlDataTableV3(ctx, {
14194
+ primaryColumns: cols.map((c) => DataColumn.fromColumn(c)),
14195
+ columns: void 0,
14196
+ tableState: ctx.data.replicateTableState,
14197
+ displayOptions: { visibility: [{
14198
+ match: { name: cols.map((c) => exactly(c.spec.name)) },
14199
+ visibility: "default"
14200
+ }] }
14201
+ });
14202
+ }).output("summaryKeyAxisId", (ctx) => {
14203
+ const cols = ctx.outputs?.resolve("summaryPf")?.getPColumns();
14204
+ const axis = (cols?.find((c) => c.spec.name === "pl7.app/vdj/affinityClass") ?? cols?.find((c) => c.spec.name === "pl7.app/vdj/kd"))?.spec.axesSpec[0];
14205
+ return axis === void 0 ? void 0 : getAxisId(axis);
14206
+ }).outputWithStatus("replicateDrilldownTable", (ctx) => {
14207
+ const cols = replicateCols(ctx);
14208
+ if (cols === void 0) return void 0;
14209
+ const filters = replicateDrilldownFilter(cols.map((c) => c.spec), ctx.data.replicateDrilldownKey);
14210
+ if (filters === void 0) return void 0;
14211
+ return createPlDataTableV3(ctx, {
14212
+ primaryColumns: cols.map((c) => DataColumn.fromColumn(c)),
14213
+ columns: void 0,
14214
+ tableState: ctx.data.replicateDrilldownTableState,
14215
+ displayOptions: { visibility: [{
14216
+ match: { name: [exactly("pl7.app/label")] },
14217
+ visibility: "hidden"
14218
+ }, {
14219
+ match: { name: cols.map((c) => exactly(c.spec.name)) },
14220
+ visibility: "default"
14221
+ }] },
14222
+ filters
14223
+ });
14224
+ }).outputWithStatus("replicatePfHandle", (ctx) => {
14225
+ const cols = replicateCols(ctx);
14226
+ if (cols === void 0) return void 0;
14227
+ return createPFrameForGraphs(ctx, cols);
14228
+ }).output("replicatePfCols", (ctx) => {
14229
+ const cols = replicateCols(ctx);
14230
+ if (cols === void 0) return void 0;
14231
+ return cols.map((c) => ({
14232
+ columnId: c.id,
14233
+ spec: c.spec
14234
+ }));
14235
+ }).title(() => "Tite-Seq Analysis").subtitle((ctx) => ctx.data.customBlockLabel || ctx.data.defaultBlockLabel || "").sections(() => sectionsFor()).done();
14073
14236
  //#endregion
14074
14237
  //#region src/index.ts
14075
14238
  const selfUrl = import.meta.url;