@platforma-open/milaboratories.repertoire-mutation-heatmap.block 1.1.5 → 1.1.7

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,126 +1,184 @@
1
- import { r as __toESM, t as __commonJSMin } from "./rolldown-runtime-B-1-B7_t.js";
2
- //#region ../kind/dist/package.js
3
- var name = "@platforma-open/milaboratories.repertoire-mutation-heatmap.kind";
4
- var version$1 = "1.0.0";
5
- //#endregion
6
- //#region ../node_modules/.pnpm/@platforma-sdk+block-kind@1.1.0/node_modules/@platforma-sdk/block-kind/dist/params.js
1
+ import { r as __toESM, t as __commonJSMin } from "./rolldown-runtime-DC62tzP2.js";
2
+ //#region ../model/dist/chart-state.js
7
3
  /**
8
- * Establish that a value is an object whose fields a kind can read — the half of a params
9
- * check every kind needs and no two kinds differ on.
10
- *
11
- * Params that arrived from a template file are `unknown`, and before a single field can be
12
- * read the value has to be an object. Worth a shared function because the check is easy to
13
- * get wrong by hand: `typeof null` is `"object"`, `Object.keys(5)` is `[]` and
14
- * `Object.keys(["a"])` is `["0"]`, so a naive test lets `null`, a number and an array through
15
- * as if they were empty params.
16
- *
17
- * What each field must *be* is the kind's own business and stays in the kind, as plain
18
- * TypeScript: this package deliberately carries no validation library, so a kind author owes
19
- * it no schema.
20
- *
21
- * A key the kind does not declare is NOT refused. A parser returns the params to use, so a
22
- * field it never read is dropped and never reaches the block — the only question was whether
23
- * to also complain, and complaining costs more than it catches. It would mean each kind
24
- * restating its own field list as strings, with nothing checking that the list stayed in step
25
- * with the type: a field added to the contract and read by the parser, but missed in the list,
26
- * would turn into a kind that refuses files that are correct. What an unexpected key can
27
- * actually mean is a params contract from a different version of the kind, and that is
28
- * guarded where it belongs — by the version in the entry's `{name}@{selector}` reference.
29
- *
30
- * An assertion rather than a parser that returns a copy, so a kind reads its fields off the
31
- * value it was handed:
32
- *
33
- * ```ts
34
- * function parseInitializationParams(value: unknown): BlockParams {
35
- * assertParamsObject(value);
4
+ * Default state for a mutation-landscape chart. Used by `init` for the placeholder and by the UI
5
+ * for each score a run produces, so the two look alike.
36
6
  *
37
- * const { numbers } = value;
38
- * if (numbers !== undefined && !isNumberArray(numbers)) {
39
- * throw new Error("'numbers' must be an array of numbers.");
40
- * }
41
- * return { numbers };
42
- * }
43
- * ```
7
+ * @param currentTab `"settings"` opens the Settings drawer, `null` leaves it closed
8
+ */
9
+ function makeLandscapeChartState(title, currentTab) {
10
+ return {
11
+ title,
12
+ template: "heatmap",
13
+ currentTab,
14
+ layersSettings: { heatmap: {
15
+ normalizationDirection: null,
16
+ transform: null,
17
+ NAValueAs: null
18
+ } },
19
+ axesSettings: {
20
+ axisX: {
21
+ cellSize: 20,
22
+ axisLabelsAngle: 45
23
+ },
24
+ axisY: {
25
+ hideAxisLabels: false,
26
+ cellSize: 20
27
+ }
28
+ }
29
+ };
30
+ }
31
+ /**
32
+ * Default state for a drill-down's partner map. Same shape as a landscape chart — one colour
33
+ * scale, no normalization, absent cells left empty — because it is the same map with one
34
+ * mutation held fixed.
35
+ */
36
+ /**
37
+ * The key a chart's saved aesthetic mapping uses for the region track, as it appears inside
38
+ * `dataBindAes`. The source id embeds the column's resolve path, so this matches it in both
39
+ * frames at once.
40
+ */
41
+ const REGION_AES_SOURCE = "region/region";
42
+ /**
43
+ * Drops a chart's saved colour mapping for the region track, so it is seeded afresh.
44
44
  *
45
- * Messages are finished sentences addressed to whoever wrote the file, because that is who
46
- * reads them: a kind's rejection is reported against the entry that carried the params.
45
+ * graph-maker reads the `pl7.app/graph/palette` annotation ONCE, when a mapping is created, and
46
+ * never reasserts it — "after that the mapping is the user's". A chart that already built its own
47
+ * mapping therefore keeps it, whatever the column now declares. Clearing the entry is the only
48
+ * way to let the pinned palette take effect on a chart that predates it.
49
+ */
50
+ function withRegionColoursReseeded(state) {
51
+ const aes = state.dataBindAes;
52
+ if (aes === void 0) return state;
53
+ const kept = Object.fromEntries(Object.entries(aes).filter(([source]) => !source.includes(REGION_AES_SOURCE)));
54
+ return {
55
+ ...state,
56
+ dataBindAes: kept
57
+ };
58
+ }
59
+ /**
60
+ * Pins "show empty rows/columns" on a drill-down chart.
47
61
  *
48
- * @param value The params as they arrived
49
- * @throws if `value` is not an object
62
+ * The partner map is sparse by nature — most positions carry no pair with the fixed mutation —
63
+ * and without this it draws only the few positions that do. The region band beneath it then
64
+ * shrinks to those, and the reader loses where in the parent they are looking. With the value
65
+ * column's axes declared dense, the full grid arrives; this is what makes it render.
50
66
  */
51
- function assertParamsObject(value) {
52
- if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`Params must be an object, not ${describe(value)}.`);
67
+ function withEmptyCellsShown(state) {
68
+ return {
69
+ ...state,
70
+ layersSettings: {
71
+ ...state.layersSettings,
72
+ heatmap: {
73
+ ...state.layersSettings?.heatmap,
74
+ showEmptyRows: true,
75
+ showEmptyColumns: true
76
+ }
77
+ }
78
+ };
53
79
  }
54
- /** What a value is, for a message that has to say why it is not an object. */
55
- function describe(value) {
56
- if (value === null) return "null";
57
- if (value === void 0) return "nothing";
58
- if (Array.isArray(value)) return "an array";
59
- return `a ${typeof value} (${JSON.stringify(value) ?? String(value)})`;
80
+ function makeDrillDownChartState() {
81
+ const base = withEmptyCellsShown(makeLandscapeChartState("", null));
82
+ return {
83
+ ...base,
84
+ axesSettings: {
85
+ ...base.axesSettings,
86
+ title: {
87
+ ...base.axesSettings?.title,
88
+ mode: "hidden"
89
+ }
90
+ }
91
+ };
60
92
  }
61
- //#endregion
62
- //#region ../node_modules/.pnpm/@platforma-sdk+block-kind@1.1.0/node_modules/@platforma-sdk/block-kind/dist/index.js
63
93
  /**
64
- * Define a block kind.
65
- *
66
- * `meta` is the kind's identity — its own `{ name, version }`. Source it from
67
- * the package's `package.json` rather than hand-typing literals, so the on-wire
68
- * `{name}@{version}` cannot drift from what npm publishes and what the S3
69
- * manifest records (all read the same `package.json`):
70
- *
71
- * ```ts
72
- * // a kind package's src/index.ts
73
- * import { name, version } from "../package.json" with { type: "json" };
74
- * export const kind = defineBlockKind<Params>({ name, version });
75
- * ```
76
- *
77
- * rolldown inlines the JSON import (tree-shaken to the two strings) into the
78
- * bundled `kind.js`, so no build-time injection is needed.
79
- *
80
- * A kind must also declare `parseInitializationParams` — the runtime check applied to params
81
- * that came from a template file rather than from typed code. See
82
- * {@link CompiledBlockKind} for what it must do.
83
- *
84
- * @typeParam BlockParams - shape of the params a block of this kind reads. Pinned both
85
- * as a type and by `parseInitializationParams`, whose return type is checked against it.
94
+ * Pins "Treat NA value as: empty" on a landscape chart's saved state.
95
+ *
96
+ * The landscape's cell axes are declared dense, so the grid now carries a record for every
97
+ * (position, state) and the substitutions no single mutant covered arrive with no value. They
98
+ * must stay empty. Seeding `makeLandscapeChartState` only reaches charts created from now on:
99
+ * graph-maker writes its whole merged layer settings back into the state it is bound to, so any
100
+ * chart opened before this change has the old default of 0 pinned in its own state, and would
101
+ * paint every uncovered substitution as a real zero-valued cell.
86
102
  */
87
- function defineBlockKind(meta) {
88
- return Object.freeze({
89
- kindSchema: "v1",
90
- name: meta.name,
91
- version: meta.version,
92
- parseInitializationParams: meta.parseInitializationParams
93
- });
103
+ function withEmptyNAValue(state) {
104
+ return {
105
+ ...state,
106
+ layersSettings: {
107
+ ...state.layersSettings,
108
+ heatmap: {
109
+ ...state.layersSettings?.heatmap,
110
+ NAValueAs: null
111
+ }
112
+ }
113
+ };
94
114
  }
95
- //#endregion
96
- //#region ../kind/dist/index.js
97
115
  /**
98
- * The same contract at runtime, for params that arrive from a template file
99
- * rather than from typed code.
116
+ * The parent-residue column's key inside both heat-map frames, as it appears inside a saved
117
+ * selector's source id. Distinct from the highlight flag's `parentFlag/isParentResidue`, which
118
+ * contains this word too but not this path.
119
+ */
120
+ const PARENT_RESIDUE_SOURCE = "parent/parentResidue";
121
+ const carriesParentResidue = (selectedSource) => selectedSource.includes(PARENT_RESIDUE_SOURCE);
122
+ /**
123
+ * Angles the X labels of a chart saved before the parent residue joined the axis, and moves the
124
+ * source across.
100
125
  *
101
- * The contract names no fields, so there is nothing to read and nothing to
102
- * validate beyond the value being an object at all. Keys a template supplies
103
- * anyway are dropped by not being read. The return type holds this in step: the
104
- * moment `BlockParams` declares a required field, `return {}` stops compiling.
126
+ * The move is belt and braces — graph-maker reapplies a default whose value has changed, so it
127
+ * would arrive anyway — but the angle is not a default option. It lives in the chart's own axes
128
+ * settings, which are seeded once when the chart is created, so without this an existing chart gets
129
+ * the two-part label flat and overlapping under a 20px column.
130
+ *
131
+ * Keyed on the parent still being an annotation track, which is what "saved before this" looks
132
+ * like. The region track is deliberately left where it is.
105
133
  */
106
- function parseInitializationParams(value) {
107
- assertParamsObject(value);
108
- return {};
134
+ function withParentOnXAxis(state) {
135
+ const options = state.optionsState;
136
+ if (options?.type !== "heatmap") return state;
137
+ const annotations = options.components.annotationsX.selectorStates;
138
+ const parent = annotations.find((selector) => carriesParentResidue(selector.selectedSource));
139
+ if (!parent) return state;
140
+ const alreadyOnX = options.components.x.selectorStates.some((selector) => carriesParentResidue(selector.selectedSource));
141
+ return {
142
+ ...state,
143
+ optionsState: {
144
+ ...options,
145
+ components: {
146
+ ...options.components,
147
+ x: alreadyOnX ? options.components.x : {
148
+ type: "simple",
149
+ selectorStates: [...options.components.x.selectorStates, parent]
150
+ },
151
+ annotationsX: {
152
+ type: "simple",
153
+ selectorStates: annotations.filter((selector) => selector !== parent)
154
+ }
155
+ }
156
+ },
157
+ axesSettings: {
158
+ ...state.axesSettings,
159
+ axisX: {
160
+ ...state.axesSettings?.axisX,
161
+ axisLabelsAngle: 45
162
+ }
163
+ }
164
+ };
165
+ }
166
+ function mapChartStates(data, rewrite) {
167
+ return {
168
+ compositionHeatmapState: rewrite(data.compositionHeatmapState),
169
+ singleMutantHeatmapState: rewrite(data.singleMutantHeatmapState),
170
+ singleMutantHeatmapStates: Object.fromEntries(Object.entries(data.singleMutantHeatmapStates).map(([key, state]) => [key, rewrite(state)]))
171
+ };
109
172
  }
110
- const kind = defineBlockKind({
111
- name,
112
- version: version$1,
113
- parseInitializationParams
114
- });
115
173
  //#endregion
116
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/plugin_handle.js
174
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/plugin_handle.js
117
175
  const PLUGIN_OUTPUT_PREFIX = "plugin-output#";
118
176
  /** Construct the output key for a plugin output in the block outputs map. */
119
177
  function pluginOutputKey(handle, outputKey) {
120
178
  return `${PLUGIN_OUTPUT_PREFIX}${handle}#${outputKey}`;
121
179
  }
122
180
  //#endregion
123
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_storage.js
181
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/block_storage.js
124
182
  /**
125
183
  * Discriminator key for BlockStorage format detection.
126
184
  * This unique hash-based key identifies data as BlockStorage vs legacy formats.
@@ -590,13 +648,14 @@ const errorMap = (issue, _ctx) => {
590
648
  message = `Invalid date`;
591
649
  break;
592
650
  case ZodIssueCode.invalid_string:
593
- if (typeof issue.validation === "object") if ("includes" in issue.validation) {
594
- message = `Invalid input: must include "${issue.validation.includes}"`;
595
- if (typeof issue.validation.position === "number") message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;
596
- } else if ("startsWith" in issue.validation) message = `Invalid input: must start with "${issue.validation.startsWith}"`;
597
- else if ("endsWith" in issue.validation) message = `Invalid input: must end with "${issue.validation.endsWith}"`;
598
- else util.assertNever(issue.validation);
599
- else if (issue.validation !== "regex") message = `Invalid ${issue.validation}`;
651
+ if (typeof issue.validation === "object") {
652
+ if ("includes" in issue.validation) {
653
+ message = `Invalid input: must include "${issue.validation.includes}"`;
654
+ if (typeof issue.validation.position === "number") message = `${message} at one or more positions greater than or equal to ${issue.validation.position}`;
655
+ } else if ("startsWith" in issue.validation) message = `Invalid input: must start with "${issue.validation.startsWith}"`;
656
+ else if ("endsWith" in issue.validation) message = `Invalid input: must end with "${issue.validation.endsWith}"`;
657
+ else util.assertNever(issue.validation);
658
+ } else if (issue.validation !== "regex") message = `Invalid ${issue.validation}`;
600
659
  else message = "Invalid";
601
660
  break;
602
661
  case ZodIssueCode.too_small:
@@ -761,8 +820,10 @@ var ParseInputLazyPath = class {
761
820
  this._key = key;
762
821
  }
763
822
  get path() {
764
- if (!this._cachedPath.length) if (Array.isArray(this._key)) this._cachedPath.push(...this._path, ...this._key);
765
- else this._cachedPath.push(...this._path, this._key);
823
+ if (!this._cachedPath.length) {
824
+ if (Array.isArray(this._key)) this._cachedPath.push(...this._path, ...this._key);
825
+ else this._cachedPath.push(...this._path, this._key);
826
+ }
766
827
  return this._cachedPath;
767
828
  }
768
829
  };
@@ -861,11 +922,12 @@ var ZodType = class {
861
922
  data,
862
923
  parsedType: getParsedType(data)
863
924
  };
864
- return handleResult(ctx, this._parseSync({
925
+ const result = this._parseSync({
865
926
  data,
866
927
  path: ctx.path,
867
928
  parent: ctx
868
- }));
929
+ });
930
+ return handleResult(ctx, result);
869
931
  }
870
932
  "~validate"(data) {
871
933
  const ctx = {
@@ -922,7 +984,8 @@ var ZodType = class {
922
984
  path: ctx.path,
923
985
  parent: ctx
924
986
  });
925
- return handleResult(ctx, await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult)));
987
+ const result = await (isAsync(maybeAsyncResult) ? maybeAsyncResult : Promise.resolve(maybeAsyncResult));
988
+ return handleResult(ctx, result);
926
989
  }
927
990
  refine(check, message) {
928
991
  const getIssueProperties = (val) => {
@@ -3475,7 +3538,8 @@ var ZodPromise = class extends ZodType {
3475
3538
  });
3476
3539
  return INVALID;
3477
3540
  }
3478
- return OK((ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data)).then((data) => {
3541
+ const promisified = ctx.parsedType === ZodParsedType.promise ? ctx.data : Promise.resolve(ctx.data);
3542
+ return OK(promisified.then((data) => {
3479
3543
  return this._def.type.parseAsync(data, {
3480
3544
  path: ctx.path,
3481
3545
  errorMap: ctx.common.contextualErrorMap
@@ -3573,30 +3637,32 @@ var ZodEffects = class extends ZodType {
3573
3637
  });
3574
3638
  });
3575
3639
  }
3576
- if (effect.type === "transform") if (ctx.common.async === false) {
3577
- const base = this._def.schema._parseSync({
3640
+ if (effect.type === "transform") {
3641
+ if (ctx.common.async === false) {
3642
+ const base = this._def.schema._parseSync({
3643
+ data: ctx.data,
3644
+ path: ctx.path,
3645
+ parent: ctx
3646
+ });
3647
+ if (!isValid(base)) return INVALID;
3648
+ const result = effect.transform(base.value, checkCtx);
3649
+ if (result instanceof Promise) throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
3650
+ return {
3651
+ status: status.value,
3652
+ value: result
3653
+ };
3654
+ } else return this._def.schema._parseAsync({
3578
3655
  data: ctx.data,
3579
3656
  path: ctx.path,
3580
3657
  parent: ctx
3658
+ }).then((base) => {
3659
+ if (!isValid(base)) return INVALID;
3660
+ return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
3661
+ status: status.value,
3662
+ value: result
3663
+ }));
3581
3664
  });
3582
- if (!isValid(base)) return INVALID;
3583
- const result = effect.transform(base.value, checkCtx);
3584
- if (result instanceof Promise) throw new Error(`Asynchronous transform encountered during synchronous parse operation. Use .parseAsync instead.`);
3585
- return {
3586
- status: status.value,
3587
- value: result
3588
- };
3589
- } else return this._def.schema._parseAsync({
3590
- data: ctx.data,
3591
- path: ctx.path,
3592
- parent: ctx
3593
- }).then((base) => {
3594
- if (!isValid(base)) return INVALID;
3595
- return Promise.resolve(effect.transform(base.value, checkCtx)).then((result) => ({
3596
- status: status.value,
3597
- value: result
3598
- }));
3599
- });
3665
+ }
3600
3666
  util.assertNever(effect);
3601
3667
  }
3602
3668
  };
@@ -3902,12 +3968,34 @@ ZodOptional.create;
3902
3968
  ZodNullable.create;
3903
3969
  ZodEffects.createWithPreprocess;
3904
3970
  ZodPipeline.create;
3971
+ const coerce = {
3972
+ string: ((arg) => ZodString.create({
3973
+ ...arg,
3974
+ coerce: true
3975
+ })),
3976
+ number: ((arg) => ZodNumber.create({
3977
+ ...arg,
3978
+ coerce: true
3979
+ })),
3980
+ boolean: ((arg) => ZodBoolean.create({
3981
+ ...arg,
3982
+ coerce: true
3983
+ })),
3984
+ bigint: ((arg) => ZodBigInt.create({
3985
+ ...arg,
3986
+ coerce: true
3987
+ })),
3988
+ date: ((arg) => ZodDate.create({
3989
+ ...arg,
3990
+ coerce: true
3991
+ }))
3992
+ };
3905
3993
  objectType({
3906
3994
  type: literalType("plain"),
3907
3995
  content: stringType()
3908
3996
  });
3909
3997
  //#endregion
3910
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
3998
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/bmodel/block_kind_ref.js
3911
3999
  /**
3912
4000
  * Compose a {@link BlockKindReference} from a kind's `name`/`version`.
3913
4001
  *
@@ -3923,12 +4011,19 @@ objectType({
3923
4011
  to: numberType().min(1)
3924
4012
  });
3925
4013
  //#endregion
3926
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/util.js
4014
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/util.js
3927
4015
  function assertNever(x) {
3928
4016
  throw new Error("Unexpected object: " + x);
3929
4017
  }
4018
+ /**
4019
+ * Return unique entries of the array by the provided id
4020
+ * For each id, the last entry is kept
4021
+ */
4022
+ function uniqueBy(array, makeId) {
4023
+ return [...new Map(array.map((e) => [makeId(e), e])).values()];
4024
+ }
3930
4025
  //#endregion
3931
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
4026
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/data_info.js
3932
4027
  /**
3933
4028
  * Type guard function that checks if the given value is a valid DataInfo.
3934
4029
  *
@@ -3997,9 +4092,7 @@ function visitDataInfo(dataInfo, cb) {
3997
4092
  cb(chunk.values);
3998
4093
  });
3999
4094
  break;
4000
- case "ParquetPartitioned":
4001
- Object.values(dataInfo.parts).forEach(cb);
4002
- break;
4095
+ case "ParquetPartitioned": Object.values(dataInfo.parts).forEach(cb);
4003
4096
  }
4004
4097
  }
4005
4098
  /**
@@ -4119,7 +4212,7 @@ function entriesToDataInfo(dataInfoEntries) {
4119
4212
  }
4120
4213
  }
4121
4214
  //#endregion
4122
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/errors.js
4215
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/errors.js
4123
4216
  var ServiceError = class extends Error {
4124
4217
  name = "ServiceError";
4125
4218
  };
@@ -4143,7 +4236,7 @@ function ensureError(value) {
4143
4236
  return new Error(stringifyValue(value));
4144
4237
  }
4145
4238
  //#endregion
4146
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/json.js
4239
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/json.js
4147
4240
  var import_canonicalize = /* @__PURE__ */ __toESM((/* @__PURE__ */ __commonJSMin(((exports, module) => {
4148
4241
  module.exports = function serialize(object) {
4149
4242
  if (typeof object === "number" && isNaN(object)) throw new Error("NaN is not allowed");
@@ -4176,7 +4269,7 @@ function parseJsonSafely(value, fallback) {
4176
4269
  }
4177
4270
  }
4178
4271
  //#endregion
4179
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4272
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/spec.js
4180
4273
  function readMetadata(metadata, key) {
4181
4274
  return metadata?.[key];
4182
4275
  }
@@ -4198,6 +4291,36 @@ function readMetadataJson(metadata, metadataJson, key) {
4198
4291
  return;
4199
4292
  }
4200
4293
  }
4294
+ /**
4295
+ * Domain keys whose value is the id of a block, rather than a qualifier of the data.
4296
+ *
4297
+ * Applying a template repoints these at the blocks of the project being built: an axis a block
4298
+ * produced names that block in its domain, so an axis left naming the exported-from project
4299
+ * resolves to nothing. Listing the keys is what makes that safe — a template's entry ids are
4300
+ * arbitrary non-empty strings, so a hand-written template may name an entry `closest`, and a
4301
+ * qualifier that happens to read `closest` must not be mistaken for a reference to it.
4302
+ *
4303
+ * A key absent from here is simply left alone, which is the behaviour from before relocation
4304
+ * reached domains at all. Adding one is therefore safe; omitting one costs only that a template
4305
+ * carrying it applies still pointing at the project it came from.
4306
+ */
4307
+ const BlockScopedDomain = /* @__PURE__ */ new Set([
4308
+ "pl7.app/blockId",
4309
+ "pl7.app/block",
4310
+ "pl7.app/redefined-by",
4311
+ "pl7.app/annotationRunId",
4312
+ "pl7.app/clonotypeAnnotationRunId",
4313
+ "pl7.app/clustering/blockId",
4314
+ "pl7.app/umap/blockId",
4315
+ "pl7.app/peptide/extractionRunId",
4316
+ "pl7.app/repertoire/extractionRunId",
4317
+ "pl7.app/antibodyVariantDesigner/designRunId",
4318
+ "pl7.app/vdj/clonotypingRunId",
4319
+ "pl7.app/vdj/clustering/blockId",
4320
+ "pl7.app/vdj/integration/blockId",
4321
+ "pl7.app/vdj/spatiotemporalAnalysis/blockId",
4322
+ "pl7.app/vdj/libraryId"
4323
+ ]);
4201
4324
  const Annotation = {
4202
4325
  AxisNature: "pl7.app/axisNature",
4203
4326
  Alphabet: "pl7.app/alphabet",
@@ -4215,6 +4338,7 @@ const Annotation = {
4215
4338
  IsDenseAxis: "pl7.app/graph/isDenseAxis",
4216
4339
  IsVirtual: "pl7.app/graph/isVirtual",
4217
4340
  Palette: "pl7.app/graph/palette",
4341
+ Shape: "pl7.app/graph/shape",
4218
4342
  Thresholds: "pl7.app/graph/thresholds",
4219
4343
  TreatAbsentValuesAs: "pl7.app/graph/treatAbsentValuesAs"
4220
4344
  },
@@ -4270,9 +4394,14 @@ const AnnotationJson = {
4270
4394
  [Annotation.Graph.Axis.SymmetricRange]: booleanType(),
4271
4395
  [Annotation.Graph.IsDenseAxis]: booleanType(),
4272
4396
  [Annotation.Graph.Palette]: objectType({
4273
- mapping: recordType(numberType()),
4274
- name: stringType()
4397
+ name: stringType(),
4398
+ mapping: recordType(coerce.number()).optional(),
4399
+ midPoint: numberType().optional(),
4400
+ min: numberType().optional(),
4401
+ max: numberType().optional(),
4402
+ log: booleanType().optional()
4275
4403
  }),
4404
+ [Annotation.Graph.Shape]: objectType({ mapping: recordType(stringType()) }),
4276
4405
  [Annotation.Graph.Thresholds]: arrayType(objectType({
4277
4406
  columnId: objectType({
4278
4407
  valueType: ValueTypeSchema,
@@ -4468,7 +4597,22 @@ function matchAxisId(query, target) {
4468
4597
  return query.name === target.name && matchDomain$1(query.domain, target.domain) && matchDomain$1(query.contextDomain, target.contextDomain);
4469
4598
  }
4470
4599
  //#endregion
4471
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4600
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/query/utils.js
4601
+ const BOOLEAN_TYPES = /* @__PURE__ */ new Set([
4602
+ "numericComparison",
4603
+ "stringEquals",
4604
+ "stringContains",
4605
+ "stringContainsFuzzy",
4606
+ "stringRegex",
4607
+ "isNull",
4608
+ "not",
4609
+ "and",
4610
+ "or",
4611
+ "isIn"
4612
+ ]);
4613
+ function isBooleanExpression(expr) {
4614
+ return BOOLEAN_TYPES.has(expr.type);
4615
+ }
4472
4616
  /**
4473
4617
  * Recursively traverses a SpecQuery tree bottom-up, applying visitor callbacks.
4474
4618
  *
@@ -4548,8 +4692,17 @@ function traverseQuerySpec(query, visitor) {
4548
4692
  function mapSpecQueryColumns(query, visitor) {
4549
4693
  return traverseQuerySpec(query, visitor);
4550
4694
  }
4695
+ /** Collects all column references from a SpecQuery tree. */
4696
+ function collectSpecQueryColumns(query) {
4697
+ const result = [];
4698
+ traverseQuerySpec(query, { column: (c) => {
4699
+ result.push(c);
4700
+ return c;
4701
+ } });
4702
+ return result;
4703
+ }
4551
4704
  //#endregion
4552
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4705
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_calculate.js
4553
4706
  function mapPTableDef(def, cb) {
4554
4707
  return {
4555
4708
  ...def,
@@ -4592,7 +4745,21 @@ function mapJoinEntry(entry, cb) {
4592
4745
  }
4593
4746
  }
4594
4747
  //#endregion
4595
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4748
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/table_common.js
4749
+ function getPTableColumnId(spec) {
4750
+ switch (spec.type) {
4751
+ case "axis": return {
4752
+ type: "axis",
4753
+ id: spec.id
4754
+ };
4755
+ case "column": return {
4756
+ type: "column",
4757
+ id: spec.id
4758
+ };
4759
+ }
4760
+ }
4761
+ //#endregion
4762
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/filtered_column.js
4596
4763
  function stringifyColumnFilteredId(key) {
4597
4764
  return canonicalizeJson(createColumnFilteredKey(key));
4598
4765
  }
@@ -4625,7 +4792,7 @@ function applyAxisFilters(spec, axisFilters) {
4625
4792
  };
4626
4793
  }
4627
4794
  //#endregion
4628
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4795
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/pool/spec.js
4629
4796
  function isPObjectId(value) {
4630
4797
  if (typeof value !== "string") return false;
4631
4798
  return isPObjectKey(parseJsonSafely(value));
@@ -4707,7 +4874,39 @@ function extractAllColumns(entry) {
4707
4874
  addAllColumns(entry);
4708
4875
  return [...columns.values()];
4709
4876
  }
4877
+ //#endregion
4878
+ //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.5/node_modules/@milaboratories/helpers/dist/utils.js
4879
+ function isNil$1(v) {
4880
+ return v === null || v === void 0;
4881
+ }
4710
4882
  Array.isArray;
4883
+ function isObject(value) {
4884
+ return typeof value === "object" && value !== null;
4885
+ }
4886
+ /**
4887
+ * Checks if the given value is a plain object.
4888
+ *
4889
+ * A plain object is defined as an object created by the `{}` literal,
4890
+ * an object created with `Object.create(null)`, or an object with a
4891
+ * prototype that resolves to `Object.prototype`.
4892
+ *
4893
+ * @param value - The value to check.
4894
+ * @returns `true` if the value is a plain object, otherwise `false`.
4895
+ *
4896
+ * @example
4897
+ * ```typescript
4898
+ * isPlainObject({}); // true
4899
+ * isPlainObject(Object.create(null)); // true
4900
+ * isPlainObject(new Date()); // false
4901
+ * isPlainObject(null); // false
4902
+ * isPlainObject([]); // false
4903
+ * ```
4904
+ */
4905
+ function isPlainObject$1(value) {
4906
+ if (!isObject(value)) return false;
4907
+ const prototype = Object.getPrototypeOf(value);
4908
+ return prototype === null || prototype === Object.prototype || Object.getPrototypeOf(prototype) === null;
4909
+ }
4711
4910
  //#endregion
4712
4911
  //#region ../node_modules/.pnpm/@milaboratories+helpers@1.14.5/node_modules/@milaboratories/helpers/dist/error.js
4713
4912
  function throwError(v) {
@@ -4715,7 +4914,7 @@ function throwError(v) {
4715
4914
  else throw v;
4716
4915
  }
4717
4916
  //#endregion
4718
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4917
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/discovered_column.js
4719
4918
  function isColumnDiscoveredKey(obj) {
4720
4919
  return typeof obj === "object" && obj !== null && "__isDiscovered" in obj;
4721
4920
  }
@@ -4735,58 +4934,254 @@ function stringifyColumnDiscoveredId(id) {
4735
4934
  }));
4736
4935
  }
4737
4936
  //#endregion
4738
- //#region ../node_modules/.pnpm/es-toolkit@1.48.1/node_modules/es-toolkit/dist/predicate/isFunction.mjs
4937
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/array/uniq.mjs
4739
4938
  /**
4740
- * Checks if `value` is a function.
4939
+ * Creates a duplicate-free version of an array.
4741
4940
  *
4742
- * @param value The value to check.
4743
- * @returns Returns `true` if `value` is a function, else `false`.
4941
+ * This function takes an array and returns a new array containing only the unique values
4942
+ * from the original array, preserving the order of first occurrence.
4943
+ *
4944
+ * @template T - The type of elements in the array.
4945
+ * @param arr - The array to process.
4946
+ * @returns A new array with only unique values from the original array.
4744
4947
  *
4745
4948
  * @example
4746
- * isFunction(Array.prototype.slice); // true
4747
- * isFunction(async function () {}); // true
4748
- * isFunction(function* () {}); // true
4749
- * isFunction(Proxy); // true
4750
- * isFunction(Int8Array); // true
4949
+ * const array = [1, 2, 2, 3, 4, 4, 5];
4950
+ * const result = uniq(array);
4951
+ * // result will be [1, 2, 3, 4, 5]
4751
4952
  */
4752
- function isFunction(value) {
4753
- return typeof value === "function";
4953
+ function uniq(arr) {
4954
+ return [...new Set(arr)];
4754
4955
  }
4755
4956
  //#endregion
4756
- //#region ../node_modules/.pnpm/es-toolkit@1.48.1/node_modules/es-toolkit/dist/predicate/isNil.mjs
4957
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/array/uniqBy.mjs
4757
4958
  /**
4758
- * Checks if a given value is null or undefined.
4959
+ * Returns a new array containing only the unique elements from the original array,
4960
+ * based on the values returned by the mapper function.
4759
4961
  *
4760
- * This function tests whether the provided value is either `null` or `undefined`.
4761
- * It returns `true` if the value is `null` or `undefined`, and `false` otherwise.
4962
+ * When duplicates are found, the first occurrence is kept and the rest are discarded.
4762
4963
  *
4763
- * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `null` or `undefined`.
4964
+ * @template T - The type of elements in the array.
4965
+ * @template U - The type of mapped elements.
4966
+ * @param arr - The array to process.
4967
+ * @param mapper - The function used to convert the array elements.
4968
+ * @returns A new array containing only the unique elements from the original array, based on the values returned by the mapper function.
4764
4969
  *
4765
- * @param x - The value to test for null or undefined.
4766
- * @returns `true` if the value is null or undefined, `false` otherwise.
4970
+ * @example
4971
+ * ```ts
4972
+ * uniqBy([1.2, 1.5, 2.1, 3.2, 5.7, 5.3, 7.19], Math.floor);
4973
+ * // [1.2, 2.1, 3.2, 5.7, 7.19]
4974
+ * ```
4767
4975
  *
4768
4976
  * @example
4769
- * const value1 = null;
4770
- * const value2 = undefined;
4771
- * const value3 = 42;
4772
- * const result1 = isNil(value1); // true
4773
- * const result2 = isNil(value2); // true
4774
- * const result3 = isNil(value3); // false
4977
+ * const array = [
4978
+ * { category: 'fruit', name: 'apple' },
4979
+ * { category: 'fruit', name: 'banana' },
4980
+ * { category: 'vegetable', name: 'carrot' },
4981
+ * ];
4982
+ * uniqBy(array, item => item.category).length
4983
+ * // 2
4984
+ * ```
4775
4985
  */
4776
- function isNil(x) {
4777
- return x == null;
4986
+ function uniqBy(arr, mapper) {
4987
+ const map = /* @__PURE__ */ new Map();
4988
+ for (let i = 0; i < arr.length; i++) {
4989
+ const item = arr[i];
4990
+ const key = mapper(item, i, arr);
4991
+ if (!map.has(key)) map.set(key, item);
4992
+ }
4993
+ return Array.from(map.values());
4778
4994
  }
4779
4995
  //#endregion
4780
- //#region ../node_modules/.pnpm/es-toolkit@1.48.1/node_modules/es-toolkit/dist/predicate/isString.mjs
4996
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/_internal/globalThis.mjs
4997
+ const globalThis_ = typeof globalThis === "object" && globalThis || typeof window === "object" && window || typeof self === "object" && self || typeof global === "object" && global || (function() {
4998
+ return this;
4999
+ })();
5000
+ //#endregion
5001
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/predicate/isTypedArray.mjs
4781
5002
  /**
4782
- * Checks if a given value is string.
5003
+ * Checks if a value is a TypedArray.
5004
+ * @param x The value to check.
5005
+ * @returns Returns true if `x` is a TypedArray, false otherwise.
4783
5006
  *
4784
- * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `string`.
5007
+ * @example
5008
+ * const arr = new Uint8Array([1, 2, 3]);
5009
+ * isTypedArray(arr); // true
4785
5010
  *
4786
- * @param value The value to check if it is string.
4787
- * @returns Returns `true` if `value` is a string, else `false`.
5011
+ * const regularArray = [1, 2, 3];
5012
+ * isTypedArray(regularArray); // false
4788
5013
  *
4789
- * @example
5014
+ * const buffer = new ArrayBuffer(16);
5015
+ * isTypedArray(buffer); // false
5016
+ */
5017
+ function isTypedArray$1(x) {
5018
+ return ArrayBuffer.isView(x) && !(x instanceof DataView);
5019
+ }
5020
+ //#endregion
5021
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/predicate/isBuffer.mjs
5022
+ /**
5023
+ * Checks if the given value is a Buffer instance.
5024
+ *
5025
+ * This function tests whether the provided value is an instance of Buffer.
5026
+ * It returns `true` if the value is a Buffer, and `false` otherwise.
5027
+ *
5028
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `Buffer`.
5029
+ *
5030
+ * @param x - The value to check if it is a Buffer.
5031
+ * @returns Returns `true` if `x` is a Buffer, else `false`.
5032
+ *
5033
+ * @example
5034
+ * const buffer = Buffer.from("test");
5035
+ * console.log(isBuffer(buffer)); // true
5036
+ *
5037
+ * const notBuffer = "not a buffer";
5038
+ * console.log(isBuffer(notBuffer)); // false
5039
+ */
5040
+ function isBuffer(x) {
5041
+ return typeof globalThis_.Buffer !== "undefined" && globalThis_.Buffer.isBuffer(x);
5042
+ }
5043
+ //#endregion
5044
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/compat/_internal/getTag.mjs
5045
+ /**
5046
+ * Gets the `toStringTag` of `value`.
5047
+ *
5048
+ * @private
5049
+ * @param {T} value The value to query.
5050
+ * @returns {string} Returns the `Object.prototype.toString.call` result.
5051
+ */
5052
+ function getTag(value) {
5053
+ if (value == null) return value === void 0 ? "[object Undefined]" : "[object Null]";
5054
+ return Object.prototype.toString.call(value);
5055
+ }
5056
+ //#endregion
5057
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/predicate/isPlainObject.mjs
5058
+ /**
5059
+ * Checks if a given value is a plain object.
5060
+ *
5061
+ * @param value - The value to check.
5062
+ * @returns True if the value is a plain object, otherwise false.
5063
+ *
5064
+ * @example
5065
+ * ```typescript
5066
+ * // ✅👇 True
5067
+ *
5068
+ * isPlainObject({ }); // ✅
5069
+ * isPlainObject({ key: 'value' }); // ✅
5070
+ * isPlainObject({ key: new Date() }); // ✅
5071
+ * isPlainObject(new Object()); // ✅
5072
+ * isPlainObject(Object.create(null)); // ✅
5073
+ * isPlainObject({ nested: { key: true} }); // ✅
5074
+ * isPlainObject(new Proxy({}, {})); // ✅
5075
+ * isPlainObject({ [Symbol('tag')]: 'A' }); // ✅
5076
+ *
5077
+ * // ✅👇 (cross-realms, node context, workers, ...)
5078
+ * const runInNewContext = await import('node:vm').then(
5079
+ * (mod) => mod.runInNewContext
5080
+ * );
5081
+ * isPlainObject(runInNewContext('({})')); // ✅
5082
+ *
5083
+ * // ❌👇 False
5084
+ *
5085
+ * class Test { };
5086
+ * isPlainObject(new Test()) // ❌
5087
+ * isPlainObject(10); // ❌
5088
+ * isPlainObject(null); // ❌
5089
+ * isPlainObject('hello'); // ❌
5090
+ * isPlainObject([]); // ❌
5091
+ * isPlainObject(new Date()); // ❌
5092
+ * isPlainObject(new Uint8Array([1])); // ❌
5093
+ * isPlainObject(Buffer.from('ABC')); // ❌
5094
+ * isPlainObject(Promise.resolve({})); // ❌
5095
+ * isPlainObject(Object.create({})); // ❌
5096
+ * isPlainObject(new (class Cls {})); // ❌
5097
+ * isPlainObject(globalThis); // ❌,
5098
+ * ```
5099
+ */
5100
+ function isPlainObject(value) {
5101
+ if (!value || typeof value !== "object") return false;
5102
+ const proto = Object.getPrototypeOf(value);
5103
+ if (!(proto === null || proto === Object.prototype || Object.getPrototypeOf(proto) === null)) return false;
5104
+ return Object.prototype.toString.call(value) === "[object Object]";
5105
+ }
5106
+ //#endregion
5107
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/predicate/isFunction.mjs
5108
+ /**
5109
+ * Checks if `value` is a function.
5110
+ *
5111
+ * @param value The value to check.
5112
+ * @returns Returns `true` if `value` is a function, else `false`.
5113
+ *
5114
+ * @example
5115
+ * isFunction(Array.prototype.slice); // true
5116
+ * isFunction(async function () {}); // true
5117
+ * isFunction(function* () {}); // true
5118
+ * isFunction(Proxy); // true
5119
+ * isFunction(Int8Array); // true
5120
+ */
5121
+ function isFunction(value) {
5122
+ return typeof value === "function";
5123
+ }
5124
+ //#endregion
5125
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/predicate/isLength.mjs
5126
+ /**
5127
+ * Checks if a given value is a valid length.
5128
+ *
5129
+ * A valid length is of type `number`, is a non-negative integer, and is less than or equal to
5130
+ * JavaScript's maximum safe integer (`Number.MAX_SAFE_INTEGER`).
5131
+ * It returns `true` if the value is a valid length, and `false` otherwise.
5132
+ *
5133
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the
5134
+ * argument to a valid length (`number`).
5135
+ *
5136
+ * @param value The value to check.
5137
+ * @returns Returns `true` if `value` is a valid length, else `false`.
5138
+ *
5139
+ * @example
5140
+ * isLength(0); // true
5141
+ * isLength(42); // true
5142
+ * isLength(-1); // false
5143
+ * isLength(1.5); // false
5144
+ * isLength(Number.MAX_SAFE_INTEGER); // true
5145
+ * isLength(Number.MAX_SAFE_INTEGER + 1); // false
5146
+ */
5147
+ function isLength(value) {
5148
+ return Number.isSafeInteger(value) && value >= 0;
5149
+ }
5150
+ //#endregion
5151
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/predicate/isNil.mjs
5152
+ /**
5153
+ * Checks if a given value is null or undefined.
5154
+ *
5155
+ * This function tests whether the provided value is either `null` or `undefined`.
5156
+ * It returns `true` if the value is `null` or `undefined`, and `false` otherwise.
5157
+ *
5158
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `null` or `undefined`.
5159
+ *
5160
+ * @param x - The value to test for null or undefined.
5161
+ * @returns `true` if the value is null or undefined, `false` otherwise.
5162
+ *
5163
+ * @example
5164
+ * const value1 = null;
5165
+ * const value2 = undefined;
5166
+ * const value3 = 42;
5167
+ * const result1 = isNil(value1); // true
5168
+ * const result2 = isNil(value2); // true
5169
+ * const result3 = isNil(value3); // false
5170
+ */
5171
+ function isNil(x) {
5172
+ return x == null;
5173
+ }
5174
+ //#endregion
5175
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/predicate/isString.mjs
5176
+ /**
5177
+ * Checks if a given value is string.
5178
+ *
5179
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to `string`.
5180
+ *
5181
+ * @param value The value to check if it is string.
5182
+ * @returns Returns `true` if `value` is a string, else `false`.
5183
+ *
5184
+ * @example
4790
5185
  * const value1 = 'abc';
4791
5186
  * const value2 = 123;
4792
5187
  * const value3 = true;
@@ -4799,7 +5194,7 @@ function isString(value) {
4799
5194
  return typeof value === "string";
4800
5195
  }
4801
5196
  //#endregion
4802
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
5197
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/ids.js
4803
5198
  /**
4804
5199
  * Canonically serializes a column key to a branded string id. Accepts both
4805
5200
  * the new {@link ColumnUniversalKey} and the deprecated {@link UniversalPColumnId}
@@ -4973,7 +5368,7 @@ function extractPObjectId(id) {
4973
5368
  throw new Error(`extractPObjectId: unrecognized column id structure: ${JSON.stringify(id)}`);
4974
5369
  }
4975
5370
  //#endregion
4976
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
5371
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/overridden.js
4977
5372
  function isColumnOverriddenKey(obj) {
4978
5373
  return typeof obj === "object" && obj !== null && "__isOverridden" in obj;
4979
5374
  }
@@ -5095,7 +5490,7 @@ function mergeRecord(a, b) {
5095
5490
  };
5096
5491
  }
5097
5492
  //#endregion
5098
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5493
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/anchored.js
5099
5494
  function axisKey(axis) {
5100
5495
  return (0, import_canonicalize.default)(getAxisId(axis));
5101
5496
  }
@@ -5341,7 +5736,7 @@ function isAnchorAxisRef(value) {
5341
5736
  return typeof value === "object" && "anchor" in value;
5342
5737
  }
5343
5738
  //#endregion
5344
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5739
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/selectors.js
5345
5740
  /**
5346
5741
  * Determines if an axis ID matches an axis selector.
5347
5742
  *
@@ -5422,7 +5817,7 @@ function legacyColumnSelectorsToPredicate(predicateOrSelectors) {
5422
5817
  else return (spec) => isPColumnSpec(spec) && matchPColumn(spec, predicateOrSelectors);
5423
5818
  }
5424
5819
  //#endregion
5425
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5820
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/spec/native_id.js
5426
5821
  function deriveNativeId(spec) {
5427
5822
  const result = {
5428
5823
  kind: spec.kind,
@@ -5434,7 +5829,7 @@ function deriveNativeId(spec) {
5434
5829
  return (0, import_canonicalize.default)(result);
5435
5830
  }
5436
5831
  //#endregion
5437
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5832
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/drivers/pframe/linker_columns.js
5438
5833
  var LinkerMap = class LinkerMap {
5439
5834
  /** Graph of linkers connected by axes (single or grouped by parents) */
5440
5835
  data;
@@ -5569,7 +5964,6 @@ var LinkerMap = class LinkerMap {
5569
5964
  switch (axesSpec.length) {
5570
5965
  case 0: return [];
5571
5966
  case 1: return [[axesSpec[0]]];
5572
- default: break;
5573
5967
  }
5574
5968
  const axisKeys = axesSpec.map((spec) => canonicalizeJson(getAxisId(spec)));
5575
5969
  const axisParentsIdxs = axesSpec.map((spec) => new Set(spec.parentAxesSpec.map((spec) => canonicalizeJson(getAxisId(spec))).map((el) => {
@@ -5612,7 +6006,7 @@ var LinkerMap = class LinkerMap {
5612
6006
  }
5613
6007
  };
5614
6008
  //#endregion
5615
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
6009
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/flags/block_flags.js
5616
6010
  /**
5617
6011
  * Required PFrames version. Bump this in lockstep with the `@milaboratories/pframes-rs-*`
5618
6012
  * version in `pnpm-workspace.yaml` so blocks built against the new SDK refuse to load on
@@ -5655,7 +6049,7 @@ function withEnrichments(ref, requireEnrichments = true) {
5655
6049
  }
5656
6050
  }
5657
6051
  //#endregion
5658
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
6052
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/value_or_error.js
5659
6053
  function mapValueInVOE(voe, cb) {
5660
6054
  return voe.ok ? {
5661
6055
  ok: true,
@@ -5663,7 +6057,7 @@ function mapValueInVOE(voe, cb) {
5663
6057
  } : voe;
5664
6058
  }
5665
6059
  //#endregion
5666
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
6060
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/resource_types.js
5667
6061
  /** Well-known resource type names used across the platform. */
5668
6062
  const ResourceTypeName = {
5669
6063
  StreamManager: "StreamManager",
@@ -5707,7 +6101,7 @@ const ResourceTypeName = {
5707
6101
  SharedEnvelope: "SharedEnvelope"
5708
6102
  };
5709
6103
  //#endregion
5710
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
6104
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/services/service_types.js
5711
6105
  const SERVICE_ID_PATTERN = /^[a-zA-Z][a-zA-Z0-9]*$/;
5712
6106
  const { service, isNodeService, isWasmService, isMainService, getServiceKind, getServiceModelMethods, getServiceUiMethods } = (() => {
5713
6107
  const typeMap = /* @__PURE__ */ new Map();
@@ -5746,7 +6140,7 @@ const { service, isNodeService, isWasmService, isMainService, getServiceKind, ge
5746
6140
  };
5747
6141
  })();
5748
6142
  //#endregion
5749
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
6143
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/services/service_declarations.js
5750
6144
  const Services = {
5751
6145
  PFrameSpec: service()({
5752
6146
  type: "wasm",
@@ -5840,7 +6234,7 @@ function resolveRequiredServices(flags) {
5840
6234
  }
5841
6235
  Object.fromEntries(Object.keys(Services).map((key) => [`requires${key}`, true]));
5842
6236
  //#endregion
5843
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
6237
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/services/service_injectors.js
5844
6238
  function buildMethodMap(pick) {
5845
6239
  const result = {};
5846
6240
  for (const id of Object.values(Services)) result[id] = [...pick(id)];
@@ -5849,7 +6243,7 @@ function buildMethodMap(pick) {
5849
6243
  buildMethodMap(getServiceUiMethods);
5850
6244
  buildMethodMap(getServiceModelMethods);
5851
6245
  //#endregion
5852
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
6246
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/accessor_traversal.js
5853
6247
  /** Resource types that hold column collections — DFS stops here and collects. */
5854
6248
  const COLLECT_TYPES = [ResourceTypeName.PFrame];
5855
6249
  /** Resource types DFS descends through when looking for PFrames. */
@@ -5957,7 +6351,7 @@ function indexPoolBlock(block) {
5957
6351
  return result;
5958
6352
  }
5959
6353
  //#endregion
5960
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
6354
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/column_registry.js
5961
6355
  /**
5962
6356
  * Id-index over a set of {@link ColumnEntriesProvider}s. Sole job:
5963
6357
  * {@link PObjectId} → {@link LeafEntry}. Generic over the accessor flavour, so
@@ -5994,7 +6388,48 @@ var ColumnRegistry = class {
5994
6388
  }
5995
6389
  };
5996
6390
  //#endregion
5997
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
6391
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/dedup.js
6392
+ /**
6393
+ * Two-track dedup over an item stream keyed by `ColumnUniversalId`:
6394
+ *
6395
+ * - **Raw `PObjectId`s** are deduped by `deriveNativeId(spec)`. The same
6396
+ * physical column reached via outputs vs. result_pool has different
6397
+ * id shapes but identical nativeId — first occurrence wins so the
6398
+ * provider order (outputs before pool) decides which id is canonical.
6399
+ * - **Non-`PObjectId` ids** (e.g. `SUniversalPColumnUniversalId`,
6400
+ * `ColumnDiscoveredId`) keep raw-id dedup — they legitimately share
6401
+ * nativeId with siblings.
6402
+ *
6403
+ * When `getSpec` returns `undefined` for a `PObjectId`, falls back to raw-id
6404
+ * dedup (so an unresolvable id still survives instead of dropping silently).
6405
+ *
6406
+ * Shared by sandbox-side `extractColumns` (column_providers) and host-side
6407
+ * `ColumnsCollectionDriverImpl.getColumns` — both layers need identical
6408
+ * dedup semantics, but operate on different concrete item types (DataColumnRecipe
6409
+ * vs. raw ColumnUniversalId).
6410
+ */
6411
+ function dedupColumns(items, getId, getSpec) {
6412
+ const seenNative = /* @__PURE__ */ new Set();
6413
+ const seenId = /* @__PURE__ */ new Set();
6414
+ const out = [];
6415
+ for (const item of items) {
6416
+ const id = getId(item);
6417
+ if (seenId.has(id)) continue;
6418
+ if (isPObjectId(id)) {
6419
+ const spec = getSpec(item);
6420
+ if (spec !== void 0) {
6421
+ const nativeId = deriveNativeId(spec);
6422
+ if (seenNative.has(nativeId)) continue;
6423
+ seenNative.add(nativeId);
6424
+ }
6425
+ }
6426
+ seenId.add(id);
6427
+ out.push(item);
6428
+ }
6429
+ return out;
6430
+ }
6431
+ //#endregion
6432
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/columns/providers.js
5998
6433
  /**
5999
6434
  * Generic entries provider over a single accessor root. Walks `<root>` once
6000
6435
  * from the supplied `rootPath`, builds an id → {@link LeafEntry} map and
@@ -6051,7 +6486,7 @@ var ResultPoolEntriesProvider = class {
6051
6486
  }
6052
6487
  };
6053
6488
  //#endregion
6054
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6489
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/template/template_ref_form.js
6055
6490
  /**
6056
6491
  * Whether `value` is a reference in the readable spelling.
6057
6492
  *
@@ -6120,7 +6555,7 @@ function expandTemplatePlRef(ref) {
6120
6555
  };
6121
6556
  }
6122
6557
  //#endregion
6123
- //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.48.0/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6558
+ //#region ../node_modules/.pnpm/@milaboratories+pl-model-common@1.51.0/node_modules/@milaboratories/pl-model-common/dist/template/template_relocate.js
6124
6559
  /**
6125
6560
  * Point every column identifier in a block's params at the blocks of the project being built.
6126
6561
  *
@@ -6136,8 +6571,13 @@ function expandTemplatePlRef(ref) {
6136
6571
  *
6137
6572
  * Rewriting is structural, never textual: an identifier is taken apart, its `blockId` fields
6138
6573
  * are replaced, and it is rebuilt canonically. That is what keeps a value that merely *looks*
6139
- * like an id — a `domain` entry, an axis filter — from being rewritten along with it, and
6140
- * what re-sorts a qualifications map whose keys are identifiers.
6574
+ * like an id — an axis filter, a domain this package can see belongs to an identifier it
6575
+ * knows — from being rewritten along with it, and what re-sorts a qualifications map whose
6576
+ * keys are identifiers.
6577
+ *
6578
+ * A domain reached on its own is the exception, and `relocateDomain` below says why: an axis is
6579
+ * qualified by the block that produced it. Only the domain keys known to name a block are
6580
+ * repointed — matching an entry id is not on its own evidence of a reference.
6141
6581
  *
6142
6582
  * An id the map does not mention is left as it is. That is the ordering rule doing its work:
6143
6583
  * a caller building the map as it creates blocks passes only the entries already created, so
@@ -6155,13 +6595,27 @@ function relocateBlockIds(params, blockIds) {
6155
6595
  if (typeof node === "string") return remapColumnIdBlockIds(node, remapBlockId);
6156
6596
  if (isColumnUniversalKey(node)) return remapColumnIdBlockIds(node, remapBlockId);
6157
6597
  if (Array.isArray(node)) return node.map(walk);
6158
- if (typeof node === "object" && node !== null) return Object.fromEntries(Object.entries(node).map(([key, value]) => [remapColumnIdBlockIds(key, remapBlockId), walk(value)]));
6598
+ if (typeof node === "object" && node !== null) return Object.fromEntries(Object.entries(node).map(([key, value]) => [remapColumnIdBlockIds(key, remapBlockId), key === "domain" && isPlainObject(value) ? relocateDomain(value) : walk(value)]));
6159
6599
  return node;
6160
6600
  };
6601
+ /**
6602
+ * The block-naming entries of a domain, repointed at the project being built: an axis a block
6603
+ * produced names that block in its domain, so those are references like any other.
6604
+ *
6605
+ * Only the keys {@link BlockScopedDomain} lists, because a template's entry ids are arbitrary
6606
+ * non-empty strings — a hand-written template may name an entry `closest`, and a qualifier
6607
+ * reading `closest` is not a reference to it. Matching the map is not on its own enough to
6608
+ * tell one from the other; the key is.
6609
+ *
6610
+ * Reached only from the generic object case — inside an identifier this package recognizes a
6611
+ * domain is spec data and stays as it is, which is what keeps an overridden column's
6612
+ * `specOverrides.domain` untouched.
6613
+ */
6614
+ const relocateDomain = (domain) => Object.fromEntries(Object.entries(domain).map(([key, value]) => [key, typeof value === "string" && BlockScopedDomain.has(key) ? remapBlockId(value) : walk(value)]));
6161
6615
  return walk(params);
6162
6616
  }
6163
6617
  //#endregion
6164
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_migrations.js
6618
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/block_migrations.js
6165
6619
  /** Create a DataVersioned wrapper with correct shape */
6166
6620
  function makeVersionedData(version, data) {
6167
6621
  return {
@@ -6739,7 +7193,7 @@ var DataModel = class DataModel {
6739
7193
  }
6740
7194
  };
6741
7195
  //#endregion
6742
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/internal.js
7196
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/internal.js
6743
7197
  /** Utility code helping to identify whether the code is running in actual UI environment */
6744
7198
  function isInUI() {
6745
7199
  return typeof globalThis.getPlatforma !== "undefined" || typeof globalThis.platforma !== "undefined";
@@ -6809,7 +7263,7 @@ function registerFutureAwait(handle, onResolve) {
6809
7263
  futureResolves.get(handle).push(onResolve);
6810
7264
  }
6811
7265
  //#endregion
6812
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
7266
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/block_storage_facade.js
6813
7267
  /**
6814
7268
  * All facade callback names as constants.
6815
7269
  * These are the source of truth - the interface is derived from these.
@@ -6847,7 +7301,7 @@ function registerFacadeCallbacks(callbacks) {
6847
7301
  for (const key of Object.values(BlockStorageFacadeCallbacks)) tryRegisterCallback(key, callbacks[key]);
6848
7302
  }
6849
7303
  //#endregion
6850
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/services/block_services.js
7304
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/services/block_services.js
6851
7305
  /**
6852
7306
  * Services required by all V3 blocks by default.
6853
7307
  * Edit this when a new service should be available to all blocks.
@@ -6863,7 +7317,7 @@ const BLOCK_SERVICE_FLAGS = {
6863
7317
  };
6864
7318
  resolveRequiredServices(BLOCK_SERVICE_FLAGS);
6865
7319
  //#endregion
6866
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/future.js
7320
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/render/future.js
6867
7321
  var FutureRef = class FutureRef {
6868
7322
  handle;
6869
7323
  postProcess;
@@ -6891,7 +7345,7 @@ var FutureRef = class FutureRef {
6891
7345
  }
6892
7346
  };
6893
7347
  //#endregion
6894
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/accessor.js
7348
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/render/accessor.js
6895
7349
  function ifDef(value, cb) {
6896
7350
  return value === void 0 ? void 0 : cb(value);
6897
7351
  }
@@ -7141,11 +7595,11 @@ var TreeNodeAccessor = class TreeNodeAccessor {
7141
7595
  }
7142
7596
  };
7143
7597
  //#endregion
7144
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/internal.js
7598
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/render/internal.js
7145
7599
  const MainAccessorName = "main";
7146
7600
  const StagingAccessorName = "staging";
7147
7601
  //#endregion
7148
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7602
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/render/util/axis_filtering.js
7149
7603
  function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7150
7604
  const sortedFilters = [...axisFilters].sort((a, b) => b[0] - a[0]);
7151
7605
  const { type } = dataInfoEntries;
@@ -7209,7 +7663,7 @@ function filterDataInfoEntries(dataInfoEntries, axisFilters) {
7209
7663
  }
7210
7664
  }
7211
7665
  //#endregion
7212
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7666
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/labels/linked_column_postfix.js
7213
7667
  /**
7214
7668
  * Structural postfix derivation for linked columns (phase 2 of `deriveDistinctLabels`).
7215
7669
  *
@@ -7392,7 +7846,7 @@ function derivePostfixes(entries, format = defaultLinkerFormatter) {
7392
7846
  });
7393
7847
  }
7394
7848
  //#endregion
7395
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7849
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/labels/derive_distinct_labels.js
7396
7850
  const DISTANCE_PENALTY = .001;
7397
7851
  const LABEL_TYPE = "__LABEL__";
7398
7852
  const LABEL_TYPE_FULL = "__LABEL__@1";
@@ -7680,7 +8134,7 @@ function repairBareByPresence(labels, minimized, records, stats, forcedSet, forc
7680
8134
  return patched;
7681
8135
  }
7682
8136
  //#endregion
7683
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/label.js
8137
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/render/util/label.js
7684
8138
  /** @deprecated Use deriveDistinctLabels */
7685
8139
  function deriveLabels(values, getSpec, options = {}) {
7686
8140
  return deriveDistinctLabels(values.map(getSpec), options).map((label, i) => ({
@@ -7689,7 +8143,7 @@ function deriveLabels(values, getSpec, options = {}) {
7689
8143
  }));
7690
8144
  }
7691
8145
  //#endregion
7692
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
8146
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/render/util/pcolumn_data.js
7693
8147
  const RT_RESOURCE_MAP = "PColumnData/ResourceMap";
7694
8148
  const RT_RESOURCE_MAP_PARTITIONED = "PColumnData/Partitioned/ResourceMap";
7695
8149
  const RT_JSON_PARTITIONED = "PColumnData/JsonPartitioned";
@@ -7730,9 +8184,7 @@ function getPartitionKeysList(acc) {
7730
8184
  break;
7731
8185
  case RT_BINARY_SUPER_PARTITIONED:
7732
8186
  case RT_JSON_SUPER_PARTITIONED:
7733
- case RT_PARQUET_SUPER_PARTITIONED:
7734
- keyLength = meta["superPartitionKeyLength"] + meta["partitionKeyLength"];
7735
- break;
8187
+ case RT_PARQUET_SUPER_PARTITIONED: keyLength = meta["superPartitionKeyLength"] + meta["partitionKeyLength"];
7736
8188
  }
7737
8189
  switch (rt) {
7738
8190
  case RT_RESOURCE_MAP:
@@ -7748,20 +8200,18 @@ function getPartitionKeysList(acc) {
7748
8200
  case RT_RESOURCE_MAP_PARTITIONED:
7749
8201
  case RT_BINARY_SUPER_PARTITIONED:
7750
8202
  case RT_JSON_SUPER_PARTITIONED:
7751
- case RT_PARQUET_SUPER_PARTITIONED:
7752
- for (const supKeyStr of acc.listInputFields()) {
7753
- const keyPrefix = [...JSON.parse(supKeyStr)];
7754
- const value = acc.resolve({
7755
- field: supKeyStr,
7756
- assertFieldType: "Input"
7757
- });
7758
- if (value !== void 0) for (let keyStr of value.listInputFields()) {
7759
- if (rt === "PColumnData/Partitioned/BinaryPartitioned") keyStr = removeIndexSuffix(keyStr).baseKey;
7760
- const key = [...keyPrefix, ...JSON.parse(keyStr)];
7761
- data.push(key);
7762
- }
8203
+ case RT_PARQUET_SUPER_PARTITIONED: for (const supKeyStr of acc.listInputFields()) {
8204
+ const keyPrefix = [...JSON.parse(supKeyStr)];
8205
+ const value = acc.resolve({
8206
+ field: supKeyStr,
8207
+ assertFieldType: "Input"
8208
+ });
8209
+ if (value !== void 0) for (let keyStr of value.listInputFields()) {
8210
+ if (rt === "PColumnData/Partitioned/BinaryPartitioned") keyStr = removeIndexSuffix(keyStr).baseKey;
8211
+ const key = [...keyPrefix, ...JSON.parse(keyStr)];
8212
+ data.push(key);
7763
8213
  }
7764
- break;
8214
+ }
7765
8215
  }
7766
8216
  return {
7767
8217
  data,
@@ -7987,7 +8437,7 @@ function allPColumnsReady(columns) {
7987
8437
  return columns.every(isPColumnReady);
7988
8438
  }
7989
8439
  //#endregion
7990
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
8440
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/render/util/column_collection.js
7991
8441
  function isPColumnValues(value) {
7992
8442
  if (!Array.isArray(value)) return false;
7993
8443
  if (value.length === 0) return true;
@@ -8265,7 +8715,7 @@ var PColumnCollection = class {
8265
8715
  }
8266
8716
  };
8267
8717
  //#endregion
8268
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8718
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/services/service_bridge.js
8269
8719
  /**
8270
8720
  * Builds a ServiceProxy from a ServiceDispatch.
8271
8721
  * Each service method call is forwarded to dispatch.callServiceMethod.
@@ -8274,7 +8724,7 @@ function createServiceProxy(dispatch) {
8274
8724
  return ((serviceId) => Object.freeze(Object.fromEntries(dispatch.getServiceMethods(serviceId).map((method) => [method, (...args) => dispatch.callServiceMethod(serviceId, method, ...args)]))));
8275
8725
  }
8276
8726
  //#endregion
8277
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/services/get_services.js
8727
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/services/get_services.js
8278
8728
  const cachedServices = /* @__PURE__ */ new WeakMap();
8279
8729
  function getService(name, deps) {
8280
8730
  const ctx = deps?.ctx ?? getCfgRenderCtx();
@@ -8288,7 +8738,7 @@ function getService(name, deps) {
8288
8738
  })();
8289
8739
  }
8290
8740
  //#endregion
8291
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8741
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/render/util/pframe_upgraders.js
8292
8742
  function patchInSetFilters(filters) {
8293
8743
  const inSetToOrEqual = (predicate) => {
8294
8744
  if (predicate.operator !== "InSet") return predicate;
@@ -8326,7 +8776,7 @@ function patchInSetFilters(filters) {
8326
8776
  return filters.map((filter) => mapFilter(filter, inSetToOrEqual));
8327
8777
  }
8328
8778
  //#endregion
8329
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/render/api.js
8779
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/render/api.js
8330
8780
  /**
8331
8781
  * Helper function to match domain objects
8332
8782
  * @param query Optional domain to match against
@@ -8775,27 +9225,27 @@ var PluginRenderCtx = class extends RenderCtxBase {
8775
9225
  }
8776
9226
  };
8777
9227
  //#endregion
8778
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/plugin_model.js
9228
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/plugin_model.js
8779
9229
  /** Internal plugin↔block handshake. `Symbol.for` (not `Symbol`) so it stays
8780
9230
  * identical across multiple `@platforma-sdk/model` copies in one process. */
8781
9231
  const CREATE_PLUGIN_MODEL = Symbol.for("@platforma-sdk/model:createPluginModel");
8782
9232
  //#endregion
8783
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/version.js
8784
- const PlatformaSDKVersion = "1.83.9";
9233
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/version.js
9234
+ const PlatformaSDKVersion = "1.84.3";
8785
9235
  //#endregion
8786
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/bconfig/types.js
9236
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/bconfig/types.js
8787
9237
  function isConfigLambda(cfgOrFh) {
8788
9238
  return cfgOrFh.__renderLambda === true;
8789
9239
  }
8790
9240
  //#endregion
8791
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
9241
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/bconfig/normalization.js
8792
9242
  function downgradeCfgOrLambda(data) {
8793
9243
  if (data === void 0) return void 0;
8794
9244
  if (isConfigLambda(data)) return data.handle;
8795
9245
  return data;
8796
9246
  }
8797
9247
  //#endregion
8798
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
9248
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/block_storage_callbacks.js
8799
9249
  /**
8800
9250
  * BlockStorage Callback Implementations - wired to facade callbacks in BlockModelV3.done().
8801
9251
  *
@@ -9149,7 +9599,7 @@ function deriveTemplateParamsFromStorage(storageJson, deriveTemplateParams) {
9149
9599
  }
9150
9600
  }
9151
9601
  //#endregion
9152
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/block_model.js
9602
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/block_model.js
9153
9603
  /**
9154
9604
  * Merges two feature flag objects with type-aware logic:
9155
9605
  * - `supports*` (boolean): OR — `true` if either side is `true`
@@ -9515,7 +9965,7 @@ var BlockModelV3 = class BlockModelV3 {
9515
9965
  }
9516
9966
  };
9517
9967
  //#endregion
9518
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
9968
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/pframe_utils/axes.js
9519
9969
  /** Create id for column copy with added keys in axes domains */
9520
9970
  const colId = (id, domains, contextDomains) => {
9521
9971
  let wid = id.toString();
@@ -9621,7 +10071,7 @@ function getAdditionalColumnsForColumn(blockAxes, column) {
9621
10071
  })];
9622
10072
  }
9623
10073
  //#endregion
9624
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
10074
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/leaf_rebrand.js
9625
10075
  /**
9626
10076
  * Replace every column leaf whose id equals `fromId` with `toId`, leaving
9627
10077
  * other column refs (linkers, sub-anchors) intact. Wrapper recipes
@@ -9639,29 +10089,38 @@ function rebrandLeafId(node, fromId, toId) {
9639
10089
  return mapSpecQueryColumns(node, { column: (id) => id === fromId ? toId : id });
9640
10090
  }
9641
10091
  //#endregion
9642
- //#region ../node_modules/.pnpm/lru-cache@11.5.1/node_modules/lru-cache/dist/esm/browser/index.min.js
9643
- var L = { hasSubscribers: !1 }, S = L, W = L;
10092
+ //#region ../node_modules/.pnpm/lru-cache@11.5.3/node_modules/lru-cache/dist/esm/browser/index.min.js
10093
+ var L = { hasSubscribers: !1 };
10094
+ var S = L;
10095
+ var W = L;
9644
10096
  var M = typeof performance == "object" && performance && typeof performance.now == "function" ? performance : Date;
9645
- var D = () => S.hasSubscribers || W.hasSubscribers, j = /* @__PURE__ */ new Set(), I = typeof process == "object" && process ? process : {}, P = (u, e, t, i) => {
9646
- typeof I.emitWarning == "function" ? I.emitWarning(u, e, t, i) : console.error(`[${t}] ${e}: ${u}`);
9647
- }, k = (u) => !j.has(u);
9648
- var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(u) ? u <= Math.pow(2, 8) ? Uint8Array : u <= Math.pow(2, 16) ? Uint16Array : u <= Math.pow(2, 32) ? Uint32Array : u <= Number.MAX_SAFE_INTEGER ? O : null : null, O = class extends Array {
10097
+ var R = () => S.hasSubscribers || W.hasSubscribers;
10098
+ var j = /* @__PURE__ */ new Set();
10099
+ var I = typeof process == "object" && process ? process : {};
10100
+ var P = (d, e, t, i) => {
10101
+ typeof I.emitWarning == "function" ? I.emitWarning(d, e, t, i) : console.error(`[${t}] ${e}: ${d}`);
10102
+ };
10103
+ var k = (d) => !j.has(d);
10104
+ var T = (d) => !!d && d === Math.floor(d) && d > 0 && isFinite(d);
10105
+ 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;
10106
+ var O = class extends Array {
9649
10107
  constructor(e) {
9650
10108
  super(e), this.fill(0);
9651
10109
  }
9652
- }, R = class u {
10110
+ };
10111
+ var x = class d {
9653
10112
  heap;
9654
10113
  length;
9655
10114
  static #o = !1;
9656
10115
  static create(e) {
9657
10116
  let t = G(e);
9658
10117
  if (!t) return [];
9659
- u.#o = !0;
9660
- let i = new u(e, t);
9661
- return u.#o = !1, i;
10118
+ d.#o = !0;
10119
+ let i = new d(e, t);
10120
+ return d.#o = !1, i;
9662
10121
  }
9663
10122
  constructor(e, t) {
9664
- if (!u.#o) throw new TypeError("instantiate Stack using Stack.create(n)");
10123
+ if (!d.#o) throw new TypeError("instantiate Stack using Stack.create(n)");
9665
10124
  this.heap = new t(e), this.length = 0;
9666
10125
  }
9667
10126
  push(e) {
@@ -9670,7 +10129,8 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
9670
10129
  pop() {
9671
10130
  return this.heap[--this.length];
9672
10131
  }
9673
- }, U = class u {
10132
+ };
10133
+ var U = class d {
9674
10134
  #o;
9675
10135
  #c;
9676
10136
  #S;
@@ -9716,7 +10176,7 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
9716
10176
  #T;
9717
10177
  #U;
9718
10178
  #f;
9719
- #x;
10179
+ #D;
9720
10180
  static unsafeExposeInternals(e) {
9721
10181
  return {
9722
10182
  starts: e.#F,
@@ -9771,87 +10231,90 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
9771
10231
  return this.#w;
9772
10232
  }
9773
10233
  constructor(e) {
9774
- let { max: t = 0, ttl: i, ttlResolution: s = 1, ttlAutopurge: n, updateAgeOnGet: r, updateAgeOnHas: h, allowStale: a, dispose: o, onInsert: d, disposeAfter: y, noDisposeOnSet: _, noUpdateTTL: c, maxSize: g = 0, maxEntrySize: f = 0, sizeCalculation: b, fetchMethod: l, memoMethod: w, noDeleteOnFetchRejection: F, noDeleteOnStaleGet: m, allowStaleOnFetchRejection: p, allowStaleOnFetchAbort: A, ignoreFetchAbort: z, backgroundFetchSize: C = 1, perf: E } = e;
10234
+ 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;
9775
10235
  if (this.backgroundFetchSize = C, E !== void 0 && typeof E?.now != "function") throw new TypeError("perf option must have a now() method if specified");
9776
10236
  if (this.#m = E ?? M, t !== 0 && !T(t)) throw new TypeError("max option must be a nonnegative integer");
9777
10237
  let v = t ? G(t) : Array;
9778
10238
  if (!v) throw new Error("invalid max value: " + t);
9779
- if (this.#o = t, this.#c = g, this.maxEntrySize = f || this.#c, this.sizeCalculation = b, this.sizeCalculation) {
10239
+ if (this.#o = t, this.#c = g, this.maxEntrySize = f || this.#c, this.sizeCalculation = y, this.sizeCalculation) {
9780
10240
  if (!this.#c && !this.maxEntrySize) throw new TypeError("cannot set sizeCalculation without setting maxSize or maxEntrySize");
9781
10241
  if (typeof this.sizeCalculation != "function") throw new TypeError("sizeCalculation set to non-function");
9782
10242
  }
9783
10243
  if (w !== void 0 && typeof w != "function") throw new TypeError("memoMethod must be a function if defined");
9784
- if (this.#I = w, l !== void 0 && typeof l != "function") throw new TypeError("fetchMethod must be a function if specified");
9785
- if (this.#M = l, this.#U = !!l, 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 = R.create(t), this.#n = 0, this.#b = 0, typeof o == "function" && (this.#S = o), typeof d == "function" && (this.#O = d), typeof y == "function" ? (this.#w = y, this.#r = []) : (this.#w = void 0, this.#r = void 0), this.#T = !!this.#S, this.#x = !!this.#O, this.#f = !!this.#w, this.noDisposeOnSet = !!_, this.noUpdateTTL = !!c, this.noDeleteOnFetchRejection = !!F, this.allowStaleOnFetchRejection = !!p, this.allowStaleOnFetchAbort = !!A, this.ignoreFetchAbort = !!z, this.maxEntrySize !== 0) {
10244
+ if (this.#I = w, a !== void 0 && typeof a != "function") throw new TypeError("fetchMethod must be a function if specified");
10245
+ 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) {
9786
10246
  if (this.#c !== 0 && !T(this.#c)) throw new TypeError("maxSize must be a positive integer if specified");
9787
10247
  if (!T(this.maxEntrySize)) throw new TypeError("maxEntrySize must be a positive integer if specified");
9788
10248
  this.#X();
9789
10249
  }
9790
- if (this.allowStale = !!a, this.noDeleteOnStaleGet = !!m, this.updateAgeOnGet = !!r, this.updateAgeOnHas = !!h, this.ttlResolution = T(s) || s === 0 ? s : 1, this.ttlAutopurge = !!n, this.ttl = i || 0, this.ttl) {
10250
+ 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) {
9791
10251
  if (!T(this.ttl)) throw new TypeError("ttl must be a positive integer if specified");
9792
10252
  this.#k();
9793
10253
  }
9794
10254
  if (this.#o === 0 && this.ttl === 0 && this.#c === 0) throw new TypeError("At least one of max, maxSize, or ttl is required");
9795
10255
  if (!this.ttlAutopurge && !this.#o && !this.#c) {
9796
- let x = "LRU_CACHE_UNBOUNDED";
9797
- k(x) && (j.add(x), P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.", "UnboundedCacheWarning", x, u));
10256
+ let D = "LRU_CACHE_UNBOUNDED";
10257
+ k(D) && (j.add(D), P("TTL caching without ttlAutopurge, max, or maxSize can result in unbounded memory consumption.", "UnboundedCacheWarning", D, d));
9798
10258
  }
9799
10259
  }
9800
10260
  getRemainingTTL(e) {
9801
- return this.#s.has(e) ? Infinity : 0;
10261
+ return this.#s.has(e) ? 1 / 0 : 0;
9802
10262
  }
9803
10263
  #k() {
9804
10264
  let e = new O(this.#o), t = new O(this.#o);
9805
10265
  this.#d = e, this.#F = t;
9806
10266
  let i = this.ttlAutopurge ? Array.from({ length: this.#o }) : void 0;
9807
- this.#g = i, this.#H = (h, a, o = this.#m.now()) => {
9808
- t[h] = a !== 0 ? o : 0, e[h] = a, s(h, a);
9809
- }, this.#D = (h) => {
10267
+ this.#g = i, this.#H = (h, r, c = this.#m.now()) => {
10268
+ t[h] = r !== 0 ? c : 0, e[h] = r, s(h, r);
10269
+ }, this.#R = (h) => {
9810
10270
  t[h] = e[h] !== 0 ? this.#m.now() : 0, s(h, e[h]);
9811
10271
  };
9812
- let s = this.ttlAutopurge ? (h, a) => {
9813
- if (i?.[h] && (clearTimeout(i[h]), i[h] = void 0), a && a !== 0 && i) {
9814
- let o = setTimeout(() => {
9815
- this.#p(h) && this.#E(this.#i[h], "expire");
9816
- }, a + 1);
9817
- o.unref && o.unref(), i[h] = o;
10272
+ let s = this.ttlAutopurge ? (h, r) => {
10273
+ if (i?.[h] && (clearTimeout(i[h]), i[h] = void 0), r && r !== 0 && i) {
10274
+ let c = setTimeout(() => {
10275
+ this.#p(h) ? (this.#E(this.#i[h], "expire"), i[h] = void 0) : s(h, l(h));
10276
+ }, r + 1);
10277
+ c.unref && c.unref(), i[h] = c;
9818
10278
  }
9819
10279
  } : () => {};
9820
- this.#v = (h, a) => {
9821
- if (e[a]) {
9822
- let o = e[a], d = t[a];
9823
- if (!o || !d) return;
9824
- h.ttl = o, h.start = d, h.now = n || r();
9825
- h.remainingTTL = o - (h.now - d);
10280
+ this.#v = (h, r) => {
10281
+ if (e[r]) {
10282
+ let c = e[r], m = t[r];
10283
+ if (!c || !m) return;
10284
+ h.ttl = c, h.start = m, h.now = n || o();
10285
+ h.remainingTTL = c - (h.now - m);
9826
10286
  }
9827
10287
  };
9828
- let n = 0, r = () => {
10288
+ let n = 0, o = () => {
9829
10289
  let h = this.#m.now();
9830
10290
  if (this.ttlResolution > 0) {
9831
10291
  n = h;
9832
- let a = setTimeout(() => n = 0, this.ttlResolution);
9833
- a.unref && a.unref();
10292
+ let r = setTimeout(() => n = 0, this.ttlResolution);
10293
+ r.unref && r.unref();
9834
10294
  }
9835
10295
  return h;
9836
10296
  };
9837
10297
  this.getRemainingTTL = (h) => {
9838
- let a = this.#s.get(h);
9839
- if (a === void 0) return 0;
9840
- let o = e[a], d = t[a];
9841
- if (!o || !d) return Infinity;
9842
- return o - ((n || r()) - d);
9843
- }, this.#p = (h) => {
9844
- let a = t[h], o = e[h];
9845
- return !!o && !!a && (n || r()) - a > o;
10298
+ let r = this.#s.get(h);
10299
+ return r === void 0 ? 0 : l(r);
10300
+ };
10301
+ let l = (h) => {
10302
+ let r = e[h], c = t[h];
10303
+ if (!r || !c) return 1 / 0;
10304
+ return r - ((n || o()) - c);
10305
+ };
10306
+ this.#p = (h) => {
10307
+ let r = t[h], c = e[h];
10308
+ return !!c && !!r && (n || o()) - r > c;
9846
10309
  };
9847
10310
  }
9848
- #D = () => {};
10311
+ #R = () => {};
9849
10312
  #v = () => {};
9850
10313
  #H = () => {};
9851
10314
  #p = () => !1;
9852
10315
  #X() {
9853
10316
  let e = new O(this.#o);
9854
- this.#b = 0, this.#_ = e, this.#R = (t) => {
10317
+ this.#b = 0, this.#_ = e, this.#x = (t) => {
9855
10318
  this.#b -= e[t], e[t] = 0;
9856
10319
  }, this.#N = (t, i, s, n) => {
9857
10320
  if (!T(s)) {
@@ -9870,7 +10333,7 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
9870
10333
  this.#b += e[t], s && (s.entrySize = i, s.totalCalculatedSize = this.#b);
9871
10334
  };
9872
10335
  }
9873
- #R = (e) => {};
10336
+ #x = (e) => {};
9874
10337
  #j = (e, t, i) => {};
9875
10338
  #N = (e, t, i, s) => {
9876
10339
  if (i || s) throw new TypeError("cannot set size without setting maxSize or maxEntrySize on cache");
@@ -9943,8 +10406,8 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
9943
10406
  if (s === void 0) return;
9944
10407
  let n = { value: s };
9945
10408
  if (this.#d && this.#F) {
9946
- let r = this.#d[t], h = this.#F[t];
9947
- if (r && h) n.ttl = r - (this.#m.now() - h), n.start = Date.now();
10409
+ let o = this.#d[t], l = this.#F[t];
10410
+ if (o && l) n.ttl = o - (this.#m.now() - l), n.start = Date.now();
9948
10411
  }
9949
10412
  return this.#_ && (n.size = this.#_[t]), n;
9950
10413
  }
@@ -9953,13 +10416,13 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
9953
10416
  for (let t of this.#A({ allowStale: !0 })) {
9954
10417
  let i = this.#i[t], s = this.#t[t], n = this.#e(s) ? s.__staleWhileFetching : s;
9955
10418
  if (n === void 0 || i === void 0) continue;
9956
- let r = { value: n };
10419
+ let o = { value: n };
9957
10420
  if (this.#d && this.#F) {
9958
- r.ttl = this.#d[t];
9959
- let h = this.#m.now() - this.#F[t];
9960
- r.start = Math.floor(Date.now() - h);
10421
+ o.ttl = this.#d[t];
10422
+ let l = this.#m.now() - this.#F[t];
10423
+ o.start = Math.floor(Date.now() - l);
9961
10424
  }
9962
- this.#_ && (r.size = this.#_[t]), e.unshift([i, r]);
10425
+ this.#_ && (o.size = this.#_[t]), e.unshift([i, o]);
9963
10426
  }
9964
10427
  return e;
9965
10428
  }
@@ -9980,19 +10443,19 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
9980
10443
  return s && S.hasSubscribers && S.publish(s), n;
9981
10444
  }
9982
10445
  #W(e, t, i, s) {
9983
- let { ttl: n = this.ttl, start: r, noDisposeOnSet: h = this.noDisposeOnSet, sizeCalculation: a = this.sizeCalculation, status: o } = i, d = this.#e(t);
9984
- if (t === void 0) return o && (o.set = "deleted"), this.delete(e), this;
9985
- let { noUpdateTTL: y = this.noUpdateTTL } = i;
9986
- o && !d && (o.value = t);
9987
- let _ = this.#N(e, t, i.size || 0, a, o);
9988
- if (this.maxEntrySize && _ > this.maxEntrySize) return this.#E(e, "set"), o && (o.set = "miss", o.maxEntrySizeExceeded = !0), this;
9989
- let c = this.#n === 0 ? void 0 : this.#s.get(e);
9990
- if (c === void 0) c = this.#n === 0 ? this.#h : this.#y.length !== 0 ? this.#y.pop() : this.#n === this.#o ? this.#G(!1) : this.#n, this.#i[c] = e, this.#t[c] = t, this.#s.set(e, c), this.#l[this.#h] = c, this.#u[c] = this.#h, this.#h = c, this.#n++, this.#j(c, _, o), o && (o.set = "add"), y = !1, this.#x && !d && this.#O?.(t, e, "add");
10446
+ let { ttl: n = this.ttl, start: o, noDisposeOnSet: l = this.noDisposeOnSet, sizeCalculation: h = this.sizeCalculation, status: r } = i, c = this.#e(t);
10447
+ if (t === void 0) return r && (r.set = "deleted"), this.delete(e), this;
10448
+ let { noUpdateTTL: m = this.noUpdateTTL } = i;
10449
+ r && !c && (r.value = t);
10450
+ let _ = this.#N(e, t, i.size || 0, h, r);
10451
+ if (this.maxEntrySize && _ > this.maxEntrySize) return this.#E(e, "set"), r && (r.set = "miss", r.maxEntrySizeExceeded = !0), this;
10452
+ let u = this.#n === 0 ? void 0 : this.#s.get(e);
10453
+ 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");
9991
10454
  else {
9992
- this.#L(c);
9993
- let g = this.#t[c];
10455
+ this.#L(u);
10456
+ let g = this.#t[u];
9994
10457
  if (t !== g) {
9995
- if (!h) if (this.#e(g)) {
10458
+ if (!l) if (this.#e(g)) {
9996
10459
  g !== s && g.__abortController.abort(/* @__PURE__ */ new Error("replaced"));
9997
10460
  let { __staleWhileFetching: f } = g;
9998
10461
  f !== void 0 && f !== t && (this.#T && this.#S?.(f, e, "set"), this.#f && this.#r?.push([
@@ -10005,13 +10468,13 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10005
10468
  e,
10006
10469
  "set"
10007
10470
  ]);
10008
- if (this.#R(c), this.#j(c, _, o), this.#t[c] = t, !d) {
10009
- let f = g && this.#e(g) ? g.__staleWhileFetching : g, b = f === void 0 ? "add" : t !== f ? "replace" : "update";
10010
- o && (o.set = b, f !== void 0 && (o.oldValue = f)), this.#x && this.onInsert?.(t, e, b);
10471
+ if (this.#x(u), this.#j(u, _, r), this.#t[u] = t, !c) {
10472
+ let f = g && this.#e(g) ? g.__staleWhileFetching : g, y = f === void 0 ? "add" : t !== f ? "replace" : "update";
10473
+ r && (r.set = y, f !== void 0 && (r.oldValue = f)), this.#D && this.onInsert?.(t, e, y);
10011
10474
  }
10012
- } else d || (o && (o.set = "update"), this.#x && this.onInsert?.(t, e, "update"));
10475
+ } else c || (r && (r.set = "update"), this.#D && this.onInsert?.(t, e, "update"));
10013
10476
  }
10014
- if (n !== 0 && !this.#d && this.#k(), this.#d && (y || this.#H(c, n, r), o && this.#v(o, c)), !h && this.#f && this.#r) {
10477
+ 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) {
10015
10478
  let g = this.#r, f;
10016
10479
  for (; f = g?.shift();) this.#w?.(...f);
10017
10480
  }
@@ -10035,12 +10498,12 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10035
10498
  #G(e) {
10036
10499
  let t = this.#a, i = this.#i[t], s = this.#t[t], n = this.#e(s);
10037
10500
  n && s.__abortController.abort(/* @__PURE__ */ new Error("evicted"));
10038
- let r = n ? s.__staleWhileFetching : s;
10039
- return (this.#T || this.#f) && r !== void 0 && (this.#T && this.#S?.(r, i, "evict"), this.#f && this.#r?.push([
10040
- r,
10501
+ let o = n ? s.__staleWhileFetching : s;
10502
+ return (this.#T || this.#f) && o !== void 0 && (this.#T && this.#S?.(o, i, "evict"), this.#f && this.#r?.push([
10503
+ o,
10041
10504
  i,
10042
10505
  "evict"
10043
- ])), this.#R(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;
10506
+ ])), 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;
10044
10507
  }
10045
10508
  has(e, t = {}) {
10046
10509
  let { status: i = S.hasSubscribers ? {} : void 0 } = t;
@@ -10051,15 +10514,15 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10051
10514
  #Y(e, t = {}) {
10052
10515
  let { updateAgeOnHas: i = this.updateAgeOnHas, status: s } = t, n = this.#s.get(e);
10053
10516
  if (n !== void 0) {
10054
- let r = this.#t[n];
10055
- if (this.#e(r) && r.__staleWhileFetching === void 0) return !1;
10517
+ let o = this.#t[n];
10518
+ if (this.#e(o) && o.__staleWhileFetching === void 0) return !1;
10056
10519
  if (this.#p(n)) s && (s.has = "stale", this.#v(s, n));
10057
- else return i && this.#D(n), s && (s.has = "hit", this.#v(s, n)), !0;
10520
+ else return i && this.#R(n), s && (s.has = "hit", this.#v(s, n)), !0;
10058
10521
  } else s && (s.has = "miss");
10059
10522
  return !1;
10060
10523
  }
10061
10524
  peek(e, t = {}) {
10062
- let { status: i = D() ? {} : void 0 } = t;
10525
+ let { status: i = R() ? {} : void 0 } = t;
10063
10526
  i && (i.op = "peek", i.key = e, i.cache = this), t.status = i;
10064
10527
  let s = this.#J(e, t);
10065
10528
  return S.hasSubscribers && S.publish(i), s;
@@ -10070,41 +10533,41 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10070
10533
  i && (i.peek = n === void 0 ? "miss" : "stale");
10071
10534
  return;
10072
10535
  }
10073
- let r = this.#t[n], h = this.#e(r) ? r.__staleWhileFetching : r;
10074
- return i && (h !== void 0 ? (i.peek = "hit", i.value = h) : i.peek = "miss"), h;
10536
+ let o = this.#t[n], l = this.#e(o) ? o.__staleWhileFetching : o;
10537
+ return i && (l !== void 0 ? (i.peek = "hit", i.value = l) : i.peek = "miss"), l;
10075
10538
  }
10076
10539
  #P(e, t, i, s) {
10077
10540
  let n = t === void 0 ? void 0 : this.#t[t];
10078
10541
  if (this.#e(n)) return n;
10079
- let r = new AbortController(), { signal: h } = i;
10080
- h?.addEventListener("abort", () => r.abort(h.reason), { signal: r.signal });
10081
- let a = {
10082
- signal: r.signal,
10542
+ let o = new AbortController(), { signal: l } = i;
10543
+ l?.addEventListener("abort", () => o.abort(l.reason), { signal: o.signal });
10544
+ let h = {
10545
+ signal: o.signal,
10083
10546
  options: i,
10084
10547
  context: s
10085
- }, o = (f, b = !1) => {
10086
- let { aborted: l } = r.signal, w = i.ignoreFetchAbort && f !== void 0, F = i.ignoreFetchAbort || !!(i.allowStaleOnFetchAbort && f !== void 0);
10087
- if (i.status && (l && !b ? (i.status.fetchAborted = !0, i.status.fetchError = r.signal.reason, w && (i.status.fetchAbortIgnored = !0)) : i.status.fetchResolved = !0), l && !w && !b) return y(r.signal.reason, F);
10088
- let m = c, p = this.#t[t];
10089
- return (p === c || p === void 0 && w && b) && (f === void 0 ? m.__staleWhileFetching !== void 0 ? this.#t[t] = m.__staleWhileFetching : this.#E(e, "fetch") : (i.status && (i.status.fetchUpdated = !0), this.#W(e, f, a.options, m))), f;
10090
- }, d = (f) => (i.status && (i.status.fetchRejected = !0, i.status.fetchError = f), y(f, !1)), y = (f, b) => {
10091
- let { aborted: l } = r.signal, w = l && i.allowStaleOnFetchAbort, F = w || i.allowStaleOnFetchRejection, m = F || i.noDeleteOnFetchRejection, p = c;
10092
- if (this.#t[t] === c && (!m || !b && 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;
10548
+ }, r = (f, y = !1) => {
10549
+ let { aborted: a } = o.signal, w = i.ignoreFetchAbort && f !== void 0, F = i.ignoreFetchAbort || !!(i.allowStaleOnFetchAbort && f !== void 0);
10550
+ 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);
10551
+ let b = u, p = this.#t[t];
10552
+ 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;
10553
+ }, c = (f) => (i.status && (i.status.fetchRejected = !0, i.status.fetchError = f), m(f, !1)), m = (f, y) => {
10554
+ let { aborted: a } = o.signal, w = a && i.allowStaleOnFetchAbort, F = w || i.allowStaleOnFetchRejection, b = F || i.noDeleteOnFetchRejection, p = u;
10555
+ 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;
10093
10556
  if (p.__returned === p) throw f;
10094
- }, _ = (f, b) => {
10095
- let l = this.#M?.(e, n, a);
10096
- r.signal.addEventListener("abort", () => {
10097
- (!i.ignoreFetchAbort || i.allowStaleOnFetchAbort) && (f(void 0), i.allowStaleOnFetchAbort && (f = (w) => o(w, !0)));
10098
- }), l && l instanceof Promise ? l.then((w) => f(w === void 0 ? void 0 : w), b) : l !== void 0 && f(l);
10557
+ }, _ = (f, y) => {
10558
+ let a = this.#M?.(e, n, h);
10559
+ o.signal.addEventListener("abort", () => {
10560
+ (!i.ignoreFetchAbort || i.allowStaleOnFetchAbort) && (f(void 0), i.allowStaleOnFetchAbort && (f = (w) => r(w, !0)));
10561
+ }), a && a instanceof Promise ? a.then((w) => f(w === void 0 ? void 0 : w), y) : a !== void 0 && f(a);
10099
10562
  };
10100
10563
  i.status && (i.status.fetchDispatched = !0);
10101
- let c = new Promise(_).then(o, d), g = Object.assign(c, {
10102
- __abortController: r,
10564
+ let u = new Promise(_).then(r, c), g = Object.assign(u, {
10565
+ __abortController: o,
10103
10566
  __staleWhileFetching: n,
10104
10567
  __returned: void 0
10105
10568
  });
10106
10569
  return t === void 0 ? (this.#W(e, g, {
10107
- ...a.options,
10570
+ ...h.options,
10108
10571
  status: void 0
10109
10572
  }), t = this.#s.get(e)) : this.#t[t] = g, g;
10110
10573
  }
@@ -10114,53 +10577,53 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10114
10577
  return !!t && t instanceof Promise && t.hasOwnProperty("__staleWhileFetching") && t.__abortController instanceof AbortController;
10115
10578
  }
10116
10579
  fetch(e, t = {}) {
10117
- let i = W.hasSubscribers, { status: s = D() ? {} : void 0 } = t;
10580
+ let i = W.hasSubscribers, { status: s = R() ? {} : void 0 } = t;
10118
10581
  t.status = s, s && t.context && (s.context = t.context);
10119
10582
  let n = this.#B(e, t);
10120
10583
  return s && i && (s.trace = !0, W.tracePromise(() => n, s).catch(() => {})), n;
10121
10584
  }
10122
10585
  async #B(e, t = {}) {
10123
- let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, ttl: r = this.ttl, noDisposeOnSet: h = this.noDisposeOnSet, size: a = 0, sizeCalculation: o = this.sizeCalculation, noUpdateTTL: d = this.noUpdateTTL, noDeleteOnFetchRejection: y = this.noDeleteOnFetchRejection, allowStaleOnFetchRejection: _ = this.allowStaleOnFetchRejection, ignoreFetchAbort: c = this.ignoreFetchAbort, allowStaleOnFetchAbort: g = this.allowStaleOnFetchAbort, context: f, forceRefresh: b = !1, status: l, signal: w } = t;
10124
- if (l && (l.op = "fetch", l.key = e, b && (l.forceRefresh = !0), l.cache = this), !this.#U) return l && (l.fetch = "get"), this.#C(e, {
10586
+ 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;
10587
+ 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, {
10125
10588
  allowStale: i,
10126
10589
  updateAgeOnGet: s,
10127
10590
  noDeleteOnStaleGet: n,
10128
- status: l
10591
+ status: a
10129
10592
  });
10130
10593
  let F = {
10131
10594
  allowStale: i,
10132
10595
  updateAgeOnGet: s,
10133
10596
  noDeleteOnStaleGet: n,
10134
- ttl: r,
10135
- noDisposeOnSet: h,
10136
- size: a,
10137
- sizeCalculation: o,
10138
- noUpdateTTL: d,
10139
- noDeleteOnFetchRejection: y,
10597
+ ttl: o,
10598
+ noDisposeOnSet: l,
10599
+ size: h,
10600
+ sizeCalculation: r,
10601
+ noUpdateTTL: c,
10602
+ noDeleteOnFetchRejection: m,
10140
10603
  allowStaleOnFetchRejection: _,
10141
10604
  allowStaleOnFetchAbort: g,
10142
- ignoreFetchAbort: c,
10143
- status: l,
10605
+ ignoreFetchAbort: u,
10606
+ status: a,
10144
10607
  signal: w
10145
- }, m = this.#s.get(e);
10146
- if (m === void 0) {
10147
- l && (l.fetch = "miss");
10148
- let p = this.#P(e, m, F, f);
10608
+ }, b = this.#s.get(e);
10609
+ if (b === void 0) {
10610
+ a && (a.fetch = "miss");
10611
+ let p = this.#P(e, b, F, f);
10149
10612
  return p.__returned = p;
10150
10613
  } else {
10151
- let p = this.#t[m];
10614
+ let p = this.#t[b];
10152
10615
  if (this.#e(p)) {
10153
10616
  let v = i && p.__staleWhileFetching !== void 0;
10154
- return l && (l.fetch = "inflight", v && (l.returnedStale = !0)), v ? p.__staleWhileFetching : p.__returned = p;
10617
+ return a && (a.fetch = "inflight", v && (a.returnedStale = !0)), v ? p.__staleWhileFetching : p.__returned = p;
10155
10618
  }
10156
- let A = this.#p(m);
10157
- if (!b && !A) return l && (l.fetch = "hit"), this.#L(m), s && this.#D(m), l && this.#v(l, m), p;
10158
- let z = this.#P(e, m, F, f), E = z.__staleWhileFetching !== void 0 && i;
10159
- return l && (l.fetch = A ? "stale" : "refresh", E && A && (l.returnedStale = !0)), E ? z.__staleWhileFetching : z.__returned = z;
10619
+ let A = this.#p(b);
10620
+ if (!y && !A) return a && (a.fetch = "hit"), this.#L(b), s && this.#R(b), a && this.#v(a, b), p;
10621
+ let z = this.#P(e, b, F, f), E = z.__staleWhileFetching !== void 0 && i;
10622
+ return a && (a.fetch = A ? "stale" : "refresh", E && A && (a.returnedStale = !0)), E ? z.__staleWhileFetching : z.__returned = z;
10160
10623
  }
10161
10624
  }
10162
10625
  forceFetch(e, t = {}) {
10163
- let i = W.hasSubscribers, { status: s = D() ? {} : void 0 } = t;
10626
+ let i = W.hasSubscribers, { status: s = R() ? {} : void 0 } = t;
10164
10627
  t.status = s, s && t.context && (s.context = t.context);
10165
10628
  let n = this.#K(e, t);
10166
10629
  return s && i && (s.trace = !0, W.tracePromise(() => n, s).catch(() => {})), n;
@@ -10179,15 +10642,15 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10179
10642
  #Q(e, t = {}) {
10180
10643
  let i = this.#I;
10181
10644
  if (!i) throw new Error("no memoMethod provided to constructor");
10182
- let { context: s, status: n, forceRefresh: r, ...h } = t;
10183
- n && r && (n.forceRefresh = !0);
10184
- let a = this.#C(e, h), o = r || a === void 0;
10185
- if (n && (n.memo = o ? "miss" : "hit", o || (n.value = a)), !o) return a;
10186
- let d = i(e, a, {
10187
- options: h,
10645
+ let { context: s, status: n, forceRefresh: o, ...l } = t;
10646
+ n && o && (n.forceRefresh = !0);
10647
+ let h = this.#C(e, l), r = o || h === void 0;
10648
+ if (n && (n.memo = r ? "miss" : "hit", r || (n.value = h)), !r) return h;
10649
+ let c = i(e, h, {
10650
+ options: l,
10188
10651
  context: s
10189
10652
  });
10190
- return n && (n.value = d), this.#W(e, d, h), d;
10653
+ return n && (n.value = c), this.#W(e, c, l), c;
10191
10654
  }
10192
10655
  get(e, t = {}) {
10193
10656
  let { status: i = S.hasSubscribers ? {} : void 0 } = t;
@@ -10196,13 +10659,13 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10196
10659
  return i && (s !== void 0 && (i.value = s), S.hasSubscribers && S.publish(i)), s;
10197
10660
  }
10198
10661
  #C(e, t = {}) {
10199
- let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, status: r } = t, h = this.#s.get(e);
10200
- if (h === void 0) {
10201
- r && (r.get = "miss");
10662
+ let { allowStale: i = this.allowStale, updateAgeOnGet: s = this.updateAgeOnGet, noDeleteOnStaleGet: n = this.noDeleteOnStaleGet, status: o } = t, l = this.#s.get(e);
10663
+ if (l === void 0) {
10664
+ o && (o.get = "miss");
10202
10665
  return;
10203
10666
  }
10204
- let a = this.#t[h], o = this.#e(a);
10205
- return r && this.#v(r, h), this.#p(h) ? o ? (r && (r.get = "stale-fetching"), i && a.__staleWhileFetching !== void 0 ? (r && (r.returnedStale = !0), a.__staleWhileFetching) : void 0) : (n || this.#E(e, "expire"), r && (r.get = "stale"), i ? (r && (r.returnedStale = !0), a) : void 0) : (r && (r.get = o ? "fetching" : "hit"), this.#L(h), s && this.#D(h), o ? a.__staleWhileFetching : a);
10667
+ let h = this.#t[l], r = this.#e(h);
10668
+ 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);
10206
10669
  }
10207
10670
  #$(e, t) {
10208
10671
  this.#u[t] = e, this.#l[e] = t;
@@ -10223,9 +10686,9 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10223
10686
  let i = !1;
10224
10687
  if (this.#n !== 0) {
10225
10688
  let s = this.#s.get(e);
10226
- 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);
10689
+ 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);
10227
10690
  else {
10228
- this.#R(s);
10691
+ this.#x(s);
10229
10692
  let n = this.#t[s];
10230
10693
  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([
10231
10694
  n,
@@ -10234,10 +10697,10 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10234
10697
  ])), this.#s.delete(e), this.#i[s] = void 0, this.#t[s] = void 0, s === this.#h) this.#h = this.#u[s];
10235
10698
  else if (s === this.#a) this.#a = this.#l[s];
10236
10699
  else {
10237
- let r = this.#u[s];
10238
- this.#l[r] = this.#l[s];
10239
- let h = this.#l[s];
10240
- this.#u[h] = this.#u[s];
10700
+ let o = this.#u[s];
10701
+ this.#l[o] = this.#l[s];
10702
+ let l = this.#l[s];
10703
+ this.#u[l] = this.#u[s];
10241
10704
  }
10242
10705
  this.#n--, this.#y.push(s);
10243
10706
  }
@@ -10276,7 +10739,7 @@ var T = (u) => !!u && u === Math.floor(u) && u > 0 && isFinite(u), G = (u) => T(
10276
10739
  }
10277
10740
  };
10278
10741
  //#endregion
10279
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
10742
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/column_providers/providers.js
10280
10743
  /**
10281
10744
  * Unified memoised factory dispatching to the right provider flavour by the
10282
10745
  * source shape:
@@ -10365,7 +10828,7 @@ function hashRawPool(rawPool) {
10365
10828
  return rawPool.map((b) => `${b.blockId}\x1f${b.prodCtx ?? ""}\x1f${b.stagingCtx ?? ""}\x1f${b.prodIncomplete ? 1 : 0}\x1f${b.stagingIncomplete ? 1 : 0}`).join("");
10366
10829
  }
10367
10830
  //#endregion
10368
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
10831
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/column_providers/index.js
10369
10832
  /**
10370
10833
  * Build the default set of ColumnsProviders for the ambient render ctx:
10371
10834
  * - `AccessorColumnsProvider` over `outputs` (if present)
@@ -10400,7 +10863,7 @@ function isColumnProvider(source) {
10400
10863
  return typeof p.getColumns === "function" && typeof p.isFinal === "function";
10401
10864
  }
10402
10865
  //#endregion
10403
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/data_column.js
10866
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/data_column.js
10404
10867
  /**
10405
10868
  * Thrown by leaf-recipe factories when the requested column is provably
10406
10869
  * absent in the active render ctx — i.e. every relevant accessor reports
@@ -10640,7 +11103,7 @@ function memoizeByEntry(fn) {
10640
11103
  };
10641
11104
  }
10642
11105
  //#endregion
10643
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
11106
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_overrided_recipe.js
10644
11107
  /**
10645
11108
  * Recipe wrapper that overlays {@link SpecOverrides} on top of any other
10646
11109
  * recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.
@@ -10778,7 +11241,7 @@ var DataColumnOverriddenRecipe = class extends ColumnOverriddenRecipe {
10778
11241
  }
10779
11242
  };
10780
11243
  //#endregion
10781
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
11244
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_filtered_recipe.js
10782
11245
  /**
10783
11246
  * Recipe wrapper that fixes the values of selected axes of an inner recipe
10784
11247
  * (axis slicing). The id is `FilteredPColumnId { source: inner.id,
@@ -10904,7 +11367,7 @@ function toAxisSelector(axis) {
10904
11367
  return selector;
10905
11368
  }
10906
11369
  //#endregion
10907
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
11370
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/index.js
10908
11371
  /**
10909
11372
  * Build a `ColumnRecipe` from a stringified id. Dispatches to the matching
10910
11373
  * concrete recipe variant based on the id's encoding and recurses on
@@ -10955,7 +11418,7 @@ function ColumnRecipeGetStatus(id, opts = {}) {
10955
11418
  }
10956
11419
  const ColumnRecipe = Object.assign(ColumnRecipeBuild, { getStatus: ColumnRecipeGetStatus });
10957
11420
  //#endregion
10958
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
11421
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/column_recipes/column_discovered_recipe.js
10959
11422
  /**
10960
11423
  * Recipe for columns identified by a {@link ColumnDiscoveredKey}: a base
10961
11424
  * column + a `path` of linkers + qualifications.
@@ -11126,7 +11589,7 @@ function referencedUniIdsOf(key) {
11126
11589
  return /* @__PURE__ */ new Set([key.column, ...(key.path ?? []).map((item) => item.column)]);
11127
11590
  }
11128
11591
  //#endregion
11129
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/column.js
11592
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/column.js
11130
11593
  /**
11131
11594
  * Unified entry point — routes between the two top-level dispatchers:
11132
11595
  * - string id (`PObjectId` / `ColumnUniversalId`) → {@link ColumnRecipe}
@@ -11140,7 +11603,7 @@ function Column(source, opts) {
11140
11603
  return DataColumn(source, opts);
11141
11604
  }
11142
11605
  //#endregion
11143
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11606
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/columns_collection.js
11144
11607
  /**
11145
11608
  * Build a {@link ColumnsCollection} from sandbox-side source descriptors.
11146
11609
  * Resolves the `columnsCollection` driver (either from `deps.driver` or via
@@ -11249,7 +11712,138 @@ function defaultCtxSources(ctx) {
11249
11712
  return [...currentBlockSources(ctx), { kind: "result_pool" }];
11250
11713
  }
11251
11714
  //#endregion
11252
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
11715
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/columns/utils.js
11716
+ /**
11717
+ * PObjectIds of every non-hit column referenced by `recipe.getQuery()`,
11718
+ * deduped in traversal order. The hit column is
11719
+ * `extractPObjectId(recipe.id)`; anything else in the query is a linker or
11720
+ * other engine-consumed column.
11721
+ *
11722
+ * Pure query walk — no registry access. Use {@link collectLinkerColumns} for
11723
+ * the resolved {@link DataColumnRecipe} variant.
11724
+ */
11725
+ function collectLinkerIds(recipe) {
11726
+ const hit = extractPObjectId(recipe.id);
11727
+ const seen = /* @__PURE__ */ new Set();
11728
+ const out = [];
11729
+ for (const id of collectSpecQueryColumns(recipe.getQuery())) {
11730
+ const bare = extractPObjectId(id);
11731
+ if (bare === hit) continue;
11732
+ if (seen.has(bare)) continue;
11733
+ seen.add(bare);
11734
+ out.push(bare);
11735
+ }
11736
+ return out;
11737
+ }
11738
+ /**
11739
+ * {@link collectLinkerIds} resolved against the ambient context as
11740
+ * {@link DataColumnRecipe} leaves. Throws if any id fails to resolve —
11741
+ * matches the contract of the legacy `resolveLinkers` it replaces.
11742
+ */
11743
+ function collectLinkerColumns(recipe, opts = {}) {
11744
+ return collectLinkerIds(recipe).map((id) => DataColumnImpl.fromId(id, opts) ?? throwError(`materializeLinkers: linker ${id} not resolvable`));
11745
+ }
11746
+ /**
11747
+ * Hit-side axis qualifications for the recipe — the ones that should land on
11748
+ * the outer-join entry wrapping this column at the consumer boundary.
11749
+ *
11750
+ * Descends {@link ColumnOverriddenRecipe} / {@link ColumnFilteredRecipe} via
11751
+ * `getInner()` until it finds a {@link ColumnDiscoveredRecipe}; otherwise
11752
+ * returns `[]`. Pure recipe walk — no query-tree introspection.
11753
+ */
11754
+ function hitQualifications(recipe) {
11755
+ return findDiscovered(recipe)?.getColumnQualifications() ?? [];
11756
+ }
11757
+ /**
11758
+ * Per-primary-column axis qualifications for the recipe — applied to the
11759
+ * outer primary anchors on this recipe's group side. Keyed by the external
11760
+ * primary column id (NOT by columns inside this recipe's own query).
11761
+ *
11762
+ * Same walk strategy as {@link hitQualifications}.
11763
+ */
11764
+ function queriesQualifications(recipe) {
11765
+ return findDiscovered(recipe)?.getQueriesQualifications() ?? {};
11766
+ }
11767
+ /**
11768
+ * Whether the recipe's underlying data resources actually carry bytes —
11769
+ * strictly stronger than `getDataStatus() === "present"`, which only tells
11770
+ * that the `.data` field is wired onto the accessor.
11771
+ *
11772
+ * Walks every physical leaf the recipe depends on via
11773
+ * {@link ColumnRecipe.getReferencedIds} (resolves each id back to a
11774
+ * {@link DataColumnRecipe} through the ambient ctx) and ANDs `hasData()` across
11775
+ * all of them. Inline {@link PColumnValues} payloads count as present.
11776
+ *
11777
+ * Returns `false` if any leaf cannot be re-resolved in `opts.ctx` (treat as
11778
+ * "not yet ready") rather than throwing — this is a UI-facing predicate, not
11779
+ * a contract assertion.
11780
+ */
11781
+ function hasColumnData(recipe, opts = {}) {
11782
+ for (const id of recipe.getReferencedIds()) {
11783
+ const leaf = DataColumnImpl.fromId(id, opts);
11784
+ if (leaf === void 0) return false;
11785
+ if (leaf.getDataStatus() !== "present") return false;
11786
+ if (!isLeafDataPresent(leaf.getData())) return false;
11787
+ }
11788
+ return true;
11789
+ }
11790
+ function isLeafDataPresent(data) {
11791
+ if (data === void 0) return false;
11792
+ if (Array.isArray(data)) return true;
11793
+ if (data instanceof TreeNodeAccessor) return data.hasData();
11794
+ if (isDataInfo(data)) {
11795
+ let ok = true;
11796
+ visitDataInfo(data, (blob) => {
11797
+ ok &&= blob.hasData();
11798
+ });
11799
+ return ok;
11800
+ }
11801
+ return false;
11802
+ }
11803
+ /**
11804
+ * Walk wrapper layers (Overridden, Filtered) until a {@link
11805
+ * ColumnDiscoveredRecipe} is found. Returns `undefined` if the recipe chain
11806
+ * has no Discovered layer (bare leaves and Overridden-over-leaf cases).
11807
+ *
11808
+ * Invariant from the wrapper classes themselves: there is at most one
11809
+ * Discovered layer in any recipe chain — Discovered is constructed only via
11810
+ * its own factory and is never re-wrapped by Discovered.
11811
+ */
11812
+ function findDiscovered(recipe) {
11813
+ let current = recipe;
11814
+ while (true) {
11815
+ if (current instanceof ColumnDiscoveredRecipe) return current;
11816
+ if (current instanceof ColumnOverriddenRecipe || current instanceof ColumnFilteredRecipe) {
11817
+ current = current.getInner();
11818
+ continue;
11819
+ }
11820
+ return;
11821
+ }
11822
+ }
11823
+ /**
11824
+ * Whether the recipe reads exactly one data column — its own — rather than
11825
+ * reaching through others.
11826
+ *
11827
+ * True for a bare leaf and for projections over one (spec overrides, axis
11828
+ * slicing): those add layers but no new columns. False when the recipe gets at
11829
+ * its data through further columns, which happens when discovery reached it via
11830
+ * a linker chain.
11831
+ *
11832
+ * **Why callers care.** A recipe over a single data column is co-indexed by its
11833
+ * own axes, so its spec is the whole truth about them. One that needs other
11834
+ * columns only lines up after they are joined in, and therefore drags axes into
11835
+ * the join that its own spec never mentions — which is why it cannot serve as a
11836
+ * primary column, and why `createPlDataTableV3` splits on this.
11837
+ *
11838
+ * The count comes from {@link ColumnRecipe.getReferencedIds}, which resolves
11839
+ * through the whole wrapper chain, so no class walk is involved and foreign
11840
+ * `ColumnRecipe` implementations are handled too.
11841
+ */
11842
+ function hasSingleDataColumn(recipe) {
11843
+ return recipe.getReferencedIds().length === 1;
11844
+ }
11845
+ //#endregion
11846
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/pframe_utils/columns.js
11253
11847
  function getAllRelatedColumns(ctx, predicate) {
11254
11848
  const columns = new PColumnCollection();
11255
11849
  columns.addColumnProvider(ctx.resultPool);
@@ -11325,7 +11919,7 @@ function discoverIntegrableColumnIds(ctx, rootColumns) {
11325
11919
  }
11326
11920
  }
11327
11921
  //#endregion
11328
- //#region ../node_modules/.pnpm/@platforma-sdk+model@1.83.9/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
11922
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/components/PFrameForGraphs.js
11329
11923
  function isHiddenFromGraphColumn(column) {
11330
11924
  return !!readAnnotationJson(column, Annotation.HideDataFromGraphs);
11331
11925
  }
@@ -11353,114 +11947,1849 @@ function createPFrameForGraphs(ctx, blockColumns) {
11353
11947
  predicate: suitableSpec
11354
11948
  }));
11355
11949
  }
11356
- (/* @__PURE__ */ __commonJSMin(((exports, module) => {
11357
- exports = module.exports = stringify;
11358
- exports.getSerialize = serializer;
11359
- function stringify(obj, replacer, spaces, cycleReplacer) {
11360
- return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces);
11361
- }
11362
- function serializer(replacer, cycleReplacer) {
11363
- var stack = [], keys = [];
11364
- if (cycleReplacer == null) cycleReplacer = function(key, value) {
11365
- if (stack[0] === value) return "[Circular ~]";
11366
- return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]";
11367
- };
11368
- return function(key, value) {
11369
- if (stack.length > 0) {
11370
- var thisPos = stack.indexOf(this);
11371
- ~thisPos ? stack.splice(thisPos + 1) : stack.push(this);
11372
- ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);
11373
- if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value);
11374
- } else stack.push(value);
11375
- return replacer == null ? value : replacer.call(this, key, value);
11376
- };
11377
- }
11378
- })))();
11379
- const PlErrorLike = objectType({
11380
- type: literalType("PlError"),
11381
- name: stringType(),
11382
- message: stringType(),
11383
- fullMessage: stringType().optional(),
11384
- stack: stringType().optional()
11385
- }).extend({
11386
- cause: lazyType(() => ErrorLike).optional(),
11387
- errors: lazyType(() => ErrorLike.array()).optional()
11388
- });
11389
- const ErrorLike = unionType([objectType({
11390
- type: literalType("StandardError"),
11391
- name: stringType(),
11392
- message: stringType(),
11393
- stack: stringType().optional()
11394
- }).extend({
11395
- cause: lazyType(() => ErrorLike).optional(),
11396
- errors: lazyType(() => ErrorLike.array()).optional()
11397
- }), PlErrorLike]);
11398
- const ErrorShape = objectType({
11399
- name: stringType(),
11400
- message: stringType(),
11401
- fullMessage: stringType().optional(),
11402
- stack: stringType().optional()
11403
- }).extend({
11404
- cause: lazyType(() => ErrorShape).optional(),
11405
- errors: lazyType(() => ErrorShape.array()).optional()
11406
- });
11407
11950
  //#endregion
11408
- //#region ../model/dist/index.js
11409
- /** A selector `name`/`domain` given as a bare string normalizes to a REGEX matcher, so an
11410
- * exact name must be spelled out. `"pl7.app/frequency"` as a regex is unanchored and `.`
11411
- * matches any character, which would also admit `pl7.app/frequencyRatio`. */
11412
- const exactMatch = (value) => [{
11413
- type: "exact",
11414
- value
11415
- }];
11416
- /** Collapse discovery hits to one recipe per storage column, first hit wins.
11417
- *
11418
- * The retired `findColumns()` keyed its result map on the leaf column, merging several
11419
- * reachability variants into one entry. `discover().getColumns()` returns one recipe PER
11420
- * variant instead, and the value these options carry is the leaf id — so without this,
11421
- * variants of one column become several dropdown entries sharing a single value. */
11422
- function dedupByLeafId(recipes) {
11423
- const seen = /* @__PURE__ */ new Set();
11424
- return recipes.filter((recipe) => {
11425
- const leaf = extractPObjectId(recipe.id);
11426
- if (seen.has(leaf)) return false;
11427
- seen.add(leaf);
11428
- return true;
11429
- });
11430
- }
11431
- const STATE_MATRIX = "pl7.app/repertoire/stateMatrix";
11432
- const LANDSCAPE_VALUE = "pl7.app/repertoire/singleMutantValue";
11433
- const LANDSCAPE_SCORE_REF = "pl7.app/repertoire/landscapeScoreRef";
11434
- const LANDSCAPE_SCORE_INDEX = "pl7.app/repertoire/landscapeScoreIndex";
11435
- const NO_DATASET_LABEL = "No dataset selected";
11951
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/filters/traverse.js
11436
11952
  /**
11437
- * Default state for a mutation-landscape chart. Used by `init` for the placeholder and by the UI
11438
- * for each score a run produces, so the two look alike.
11953
+ * Recursively traverses a FilterSpec tree bottom-up, applying visitor callbacks.
11439
11954
  *
11440
- * @param currentTab `"settings"` opens the Settings drawer, `null` leaves it closed
11955
+ * Entries with `{ type: undefined }` inside `and`/`or` arrays are skipped
11956
+ * (these represent unfilled filter slots in the UI).
11957
+ *
11958
+ * Traversal order:
11959
+ * 1. Recurse into child filters (`and`/`or`/`not`)
11960
+ * 2. Apply the corresponding visitor callback with already-traversed children
11961
+ * 3. For leaf nodes, call `leaf` directly
11441
11962
  */
11442
- function makeLandscapeChartState(title, currentTab) {
11443
- return {
11444
- title,
11445
- template: "heatmap",
11446
- currentTab,
11447
- layersSettings: { heatmap: {
11448
- normalizationDirection: null,
11449
- transform: null
11450
- } },
11451
- axesSettings: {
11452
- axisX: { cellSize: 20 },
11453
- axisY: {
11454
- hideAxisLabels: false,
11455
- cellSize: 20
11456
- }
11457
- }
11963
+ function traverseFilterSpec(filter, visitor) {
11964
+ return traverseFilterSpecImpl(filter, visitor);
11965
+ }
11966
+ /** Internal implementation with simple generics for clean recursion. */
11967
+ function traverseFilterSpecImpl(filter, visitor) {
11968
+ switch (filter.type) {
11969
+ case "and": return visitor.and(filter.filters.filter((f) => f.type !== void 0).map((f) => traverseFilterSpecImpl(f, visitor)));
11970
+ case "or": return visitor.or(filter.filters.filter((f) => f.type !== void 0).map((f) => traverseFilterSpecImpl(f, visitor)));
11971
+ case "not": return visitor.not(traverseFilterSpecImpl(filter.filter, visitor));
11972
+ default: return visitor.leaf(filter);
11973
+ }
11974
+ }
11975
+ /** Collects all column references (`column` and `rhs` fields) from filter leaves. */
11976
+ function collectFilterSpecColumns(filter) {
11977
+ return traverseFilterSpec(filter, {
11978
+ leaf: (leaf) => {
11979
+ const cols = [];
11980
+ if ("column" in leaf && leaf.column !== void 0) cols.push(leaf.column);
11981
+ if ("rhs" in leaf && leaf.rhs !== void 0) cols.push(leaf.rhs);
11982
+ return cols;
11983
+ },
11984
+ and: (results) => results.flat(),
11985
+ or: (results) => results.flat(),
11986
+ not: (result) => result
11987
+ });
11988
+ }
11989
+ //#endregion
11990
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/filters/converters/filterToQuery.js
11991
+ /** Converts a QueryColumnId object into a SpecQueryExpression reference. */
11992
+ function resolveColumnRef(col) {
11993
+ return col.type === "axis" ? {
11994
+ type: "axisRef",
11995
+ value: col.id
11996
+ } : {
11997
+ type: "columnRef",
11998
+ value: col.id
11999
+ };
12000
+ }
12001
+ /** Converts a FilterSpec tree into a SpecQueryExpression. */
12002
+ function filterSpecToSpecQueryExpr(filter) {
12003
+ return traverseFilterSpec(filter, {
12004
+ leaf: leafToSpecQueryExpr,
12005
+ and: (inputs) => {
12006
+ if (inputs.length === 0) throw new Error("AND filter requires at least one operand");
12007
+ return {
12008
+ type: "and",
12009
+ input: inputs
12010
+ };
12011
+ },
12012
+ or: (inputs) => {
12013
+ if (inputs.length === 0) throw new Error("OR filter requires at least one operand");
12014
+ return {
12015
+ type: "or",
12016
+ input: inputs
12017
+ };
12018
+ },
12019
+ not: (input) => ({
12020
+ type: "not",
12021
+ input
12022
+ })
12023
+ });
12024
+ }
12025
+ function leafToSpecQueryExpr(filter) {
12026
+ switch (filter.type) {
12027
+ case "patternEquals": return {
12028
+ type: "stringEquals",
12029
+ input: resolveColumnRef(filter.column),
12030
+ value: filter.value,
12031
+ caseInsensitive: false
12032
+ };
12033
+ case "patternNotEquals": return {
12034
+ type: "not",
12035
+ input: {
12036
+ type: "stringEquals",
12037
+ input: resolveColumnRef(filter.column),
12038
+ value: filter.value,
12039
+ caseInsensitive: false
12040
+ }
12041
+ };
12042
+ case "patternContainSubsequence": return {
12043
+ type: "stringContains",
12044
+ input: resolveColumnRef(filter.column),
12045
+ value: filter.value,
12046
+ caseInsensitive: false
12047
+ };
12048
+ case "patternNotContainSubsequence": return {
12049
+ type: "not",
12050
+ input: {
12051
+ type: "stringContains",
12052
+ input: resolveColumnRef(filter.column),
12053
+ value: filter.value,
12054
+ caseInsensitive: false
12055
+ }
12056
+ };
12057
+ case "patternMatchesRegularExpression": return {
12058
+ type: "stringRegex",
12059
+ input: resolveColumnRef(filter.column),
12060
+ value: filter.value
12061
+ };
12062
+ case "patternFuzzyContainSubsequence": return {
12063
+ type: "stringContainsFuzzy",
12064
+ input: resolveColumnRef(filter.column),
12065
+ value: filter.value,
12066
+ maxEdits: filter.maxEdits ?? 1,
12067
+ caseInsensitive: false,
12068
+ substitutionsOnly: filter.substitutionsOnly ?? false,
12069
+ wildcard: filter.wildcard ?? null
12070
+ };
12071
+ case "equal": return {
12072
+ type: "numericComparison",
12073
+ operand: "eq",
12074
+ left: resolveColumnRef(filter.column),
12075
+ right: {
12076
+ type: "constant",
12077
+ value: filter.x
12078
+ }
12079
+ };
12080
+ case "notEqual": return {
12081
+ type: "numericComparison",
12082
+ operand: "ne",
12083
+ left: resolveColumnRef(filter.column),
12084
+ right: {
12085
+ type: "constant",
12086
+ value: filter.x
12087
+ }
12088
+ };
12089
+ case "lessThan": return {
12090
+ type: "numericComparison",
12091
+ operand: "lt",
12092
+ left: resolveColumnRef(filter.column),
12093
+ right: {
12094
+ type: "constant",
12095
+ value: filter.x
12096
+ }
12097
+ };
12098
+ case "greaterThan": return {
12099
+ type: "numericComparison",
12100
+ operand: "gt",
12101
+ left: resolveColumnRef(filter.column),
12102
+ right: {
12103
+ type: "constant",
12104
+ value: filter.x
12105
+ }
12106
+ };
12107
+ case "lessThanOrEqual": return {
12108
+ type: "numericComparison",
12109
+ operand: "le",
12110
+ left: resolveColumnRef(filter.column),
12111
+ right: {
12112
+ type: "constant",
12113
+ value: filter.x
12114
+ }
12115
+ };
12116
+ case "greaterThanOrEqual": return {
12117
+ type: "numericComparison",
12118
+ operand: "ge",
12119
+ left: resolveColumnRef(filter.column),
12120
+ right: {
12121
+ type: "constant",
12122
+ value: filter.x
12123
+ }
12124
+ };
12125
+ case "equalToColumn": return {
12126
+ type: "numericComparison",
12127
+ operand: "eq",
12128
+ left: resolveColumnRef(filter.column),
12129
+ right: resolveColumnRef(filter.rhs)
12130
+ };
12131
+ case "lessThanColumn": {
12132
+ const left = resolveColumnRef(filter.column);
12133
+ const right = resolveColumnRef(filter.rhs);
12134
+ if (filter.minDiff !== void 0 && filter.minDiff !== 0) return {
12135
+ type: "numericComparison",
12136
+ operand: "lt",
12137
+ left: {
12138
+ type: "numericBinary",
12139
+ operand: "add",
12140
+ left,
12141
+ right: {
12142
+ type: "constant",
12143
+ value: filter.minDiff
12144
+ }
12145
+ },
12146
+ right
12147
+ };
12148
+ return {
12149
+ type: "numericComparison",
12150
+ operand: "lt",
12151
+ left,
12152
+ right
12153
+ };
12154
+ }
12155
+ case "greaterThanColumn": {
12156
+ const left = resolveColumnRef(filter.column);
12157
+ const right = resolveColumnRef(filter.rhs);
12158
+ if (filter.minDiff !== void 0 && filter.minDiff !== 0) return {
12159
+ type: "numericComparison",
12160
+ operand: "gt",
12161
+ left: {
12162
+ type: "numericBinary",
12163
+ operand: "add",
12164
+ left,
12165
+ right: {
12166
+ type: "constant",
12167
+ value: filter.minDiff
12168
+ }
12169
+ },
12170
+ right
12171
+ };
12172
+ return {
12173
+ type: "numericComparison",
12174
+ operand: "gt",
12175
+ left,
12176
+ right
12177
+ };
12178
+ }
12179
+ case "lessThanColumnOrEqual": {
12180
+ const left = resolveColumnRef(filter.column);
12181
+ const right = resolveColumnRef(filter.rhs);
12182
+ if (filter.minDiff !== void 0 && filter.minDiff !== 0) return {
12183
+ type: "numericComparison",
12184
+ operand: "le",
12185
+ left: {
12186
+ type: "numericBinary",
12187
+ operand: "add",
12188
+ left,
12189
+ right: {
12190
+ type: "constant",
12191
+ value: filter.minDiff
12192
+ }
12193
+ },
12194
+ right
12195
+ };
12196
+ return {
12197
+ type: "numericComparison",
12198
+ operand: "le",
12199
+ left,
12200
+ right
12201
+ };
12202
+ }
12203
+ case "greaterThanColumnOrEqual": {
12204
+ const left = resolveColumnRef(filter.column);
12205
+ const right = resolveColumnRef(filter.rhs);
12206
+ if (filter.minDiff !== void 0 && filter.minDiff !== 0) return {
12207
+ type: "numericComparison",
12208
+ operand: "ge",
12209
+ left: {
12210
+ type: "numericBinary",
12211
+ operand: "add",
12212
+ left,
12213
+ right: {
12214
+ type: "constant",
12215
+ value: filter.minDiff
12216
+ }
12217
+ },
12218
+ right
12219
+ };
12220
+ return {
12221
+ type: "numericComparison",
12222
+ operand: "ge",
12223
+ left,
12224
+ right
12225
+ };
12226
+ }
12227
+ case "inSet": return {
12228
+ type: "isIn",
12229
+ input: resolveColumnRef(filter.column),
12230
+ set: filter.value,
12231
+ negate: false
12232
+ };
12233
+ case "notInSet": return {
12234
+ type: "isIn",
12235
+ input: resolveColumnRef(filter.column),
12236
+ set: filter.value,
12237
+ negate: true
12238
+ };
12239
+ case "isNA": return {
12240
+ type: "isNull",
12241
+ input: resolveColumnRef(filter.column)
12242
+ };
12243
+ case "isNotNA": return {
12244
+ type: "not",
12245
+ input: {
12246
+ type: "isNull",
12247
+ input: resolveColumnRef(filter.column)
12248
+ }
12249
+ };
12250
+ case "ifNa": return {
12251
+ type: "fillNull",
12252
+ input: resolveColumnRef(filter.column),
12253
+ replacement: {
12254
+ type: "constant",
12255
+ value: filter.replacement
12256
+ }
12257
+ };
12258
+ case "topN":
12259
+ case "bottomN": throw new Error(`Filter type "${filter.type}" is not supported in query expressions`);
12260
+ case void 0: throw new Error("Filter type is undefined");
12261
+ default: assertNever(filter);
12262
+ }
12263
+ }
12264
+ //#endregion
12265
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/compat/predicate/isArrayLike.mjs
12266
+ /**
12267
+ * Checks if `value` is array-like.
12268
+ *
12269
+ * @param value The value to check.
12270
+ * @returns Returns `true` if `value` is array-like, else `false`.
12271
+ *
12272
+ * @example
12273
+ * isArrayLike([1, 2, 3]); // true
12274
+ * isArrayLike('abc'); // true
12275
+ * isArrayLike({ 0: 'a', length: 1 }); // true
12276
+ * isArrayLike({}); // false
12277
+ * isArrayLike(null); // false
12278
+ * isArrayLike(undefined); // false
12279
+ */
12280
+ function isArrayLike(value) {
12281
+ return value != null && typeof value !== "function" && isLength(value.length);
12282
+ }
12283
+ //#endregion
12284
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/compat/predicate/isArguments.mjs
12285
+ /**
12286
+ * Checks if the given value is an arguments object.
12287
+ *
12288
+ * This function tests whether the provided value is an arguments object or not.
12289
+ * It returns `true` if the value is an arguments object, and `false` otherwise.
12290
+ *
12291
+ * This function can also serve as a type predicate in TypeScript, narrowing the type of the argument to an arguments object.
12292
+ *
12293
+ * @param value - The value to test if it is an arguments object.
12294
+ * @returns `true` if the value is an arguments, `false` otherwise.
12295
+ *
12296
+ * @example
12297
+ * const args = (function() { return arguments; })();
12298
+ * const strictArgs = (function() { 'use strict'; return arguments; })();
12299
+ * const value = [1, 2, 3];
12300
+ *
12301
+ * console.log(isArguments(args)); // true
12302
+ * console.log(isArguments(strictArgs)); // true
12303
+ * console.log(isArguments(value)); // false
12304
+ */
12305
+ function isArguments(value) {
12306
+ return value !== null && typeof value === "object" && getTag(value) === "[object Arguments]";
12307
+ }
12308
+ //#endregion
12309
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/compat/predicate/isTypedArray.mjs
12310
+ /**
12311
+ * Checks if a value is a TypedArray.
12312
+ * @param x The value to check.
12313
+ * @returns Returns true if `x` is a TypedArray, false otherwise.
12314
+ *
12315
+ * @example
12316
+ * const arr = new Uint8Array([1, 2, 3]);
12317
+ * isTypedArray(arr); // true
12318
+ *
12319
+ * const regularArray = [1, 2, 3];
12320
+ * isTypedArray(regularArray); // false
12321
+ *
12322
+ * const buffer = new ArrayBuffer(16);
12323
+ * isTypedArray(buffer); // false
12324
+ */
12325
+ function isTypedArray(x) {
12326
+ return isTypedArray$1(x);
12327
+ }
12328
+ //#endregion
12329
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/compat/_internal/isPrototype.mjs
12330
+ function isPrototype(value) {
12331
+ const constructor = value?.constructor;
12332
+ return value === (typeof constructor === "function" ? constructor.prototype : Object.prototype);
12333
+ }
12334
+ //#endregion
12335
+ //#region ../node_modules/.pnpm/es-toolkit@1.52.0/node_modules/es-toolkit/dist/compat/predicate/isEmpty.mjs
12336
+ /**
12337
+ * Checks if a given value is empty.
12338
+ *
12339
+ * - If the given value is a string, checks if it is an empty string.
12340
+ * - If the given value is an array, `Map`, or `Set`, checks if its size is 0.
12341
+ * - If the given value is an [array-like object](../predicate/isArrayLike.md), checks if its length is 0.
12342
+ * - If the given value is an object, checks if it is an empty object with no properties.
12343
+ * - Primitive values (booleans, numbers, or bigints) are considered empty.
12344
+ *
12345
+ * @param [value] - The value to check.
12346
+ * @returns `true` if the value is empty, `false` otherwise.
12347
+ *
12348
+ * @example
12349
+ * isEmpty(); // true
12350
+ * isEmpty(null); // true
12351
+ * isEmpty(""); // true
12352
+ * isEmpty([]); // true
12353
+ * isEmpty({}); // true
12354
+ * isEmpty(new Map()); // true
12355
+ * isEmpty(new Set()); // true
12356
+ * isEmpty("hello"); // false
12357
+ * isEmpty([1, 2, 3]); // false
12358
+ * isEmpty({ a: 1 }); // false
12359
+ * isEmpty(new Map([["key", "value"]])); // false
12360
+ * isEmpty(new Set([1, 2, 3])); // false
12361
+ */
12362
+ function isEmpty(value) {
12363
+ if (value == null) return true;
12364
+ if (isArrayLike(value)) {
12365
+ if (typeof value.splice !== "function" && typeof value !== "string" && !isBuffer(value) && !isTypedArray(value) && !isArguments(value)) return false;
12366
+ return value.length === 0;
12367
+ }
12368
+ if (typeof value === "object" || typeof value === "function") {
12369
+ if (value instanceof Map || value instanceof Set) return value.size === 0;
12370
+ const keys = Object.keys(value);
12371
+ if (isPrototype(value)) return keys.filter((x) => x !== "constructor").length === 0;
12372
+ return keys.length === 0;
12373
+ }
12374
+ return true;
12375
+ }
12376
+ //#endregion
12377
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/filters/distill.js
12378
+ /**
12379
+ * Strips non-FilterSpec metadata (whitelist approach) and removes
12380
+ * unfilled leaves (type is undefined or any required field is undefined).
12381
+ */
12382
+ function distillFilterSpec(filter) {
12383
+ if (filter == null) return null;
12384
+ return traverseFilterSpec(filter, {
12385
+ leaf: (leaf) => {
12386
+ const distilled = distillLeaf(leaf);
12387
+ return isFilledLeaf(distilled) ? distilled : null;
12388
+ },
12389
+ and: (results) => {
12390
+ const filtered = results.filter((f) => f !== null);
12391
+ return filtered.length === 0 ? null : {
12392
+ type: "and",
12393
+ filters: filtered
12394
+ };
12395
+ },
12396
+ or: (results) => {
12397
+ const filtered = results.filter((f) => f !== null);
12398
+ return filtered.length === 0 ? null : {
12399
+ type: "or",
12400
+ filters: filtered
12401
+ };
12402
+ },
12403
+ not: (result) => result === null ? null : {
12404
+ type: "not",
12405
+ filter: result
12406
+ }
12407
+ });
12408
+ }
12409
+ function distillLeaf(node) {
12410
+ const result = {};
12411
+ for (const [key, value] of Object.entries(node)) if (KNOWN_LEAF_KEYS.has(key)) result[key] = value;
12412
+ return result;
12413
+ }
12414
+ /** Returns true if the leaf is filled — type is defined and every required field per-type is filled. */
12415
+ function isFilledLeaf(node) {
12416
+ if (isNil$1(node.type)) return false;
12417
+ const required = REQUIRED_KEYS_BY_TYPE[node.type];
12418
+ const record = node;
12419
+ return required.every((key) => isFilledValue(record[key]));
12420
+ }
12421
+ /**
12422
+ * Returns true if the value is considered "filled":
12423
+ * - primitives (number, boolean): always true
12424
+ * - string: non-empty after trim
12425
+ * - array: non-empty AND every item is filled
12426
+ * - plain object: non-empty AND every field value is filled
12427
+ * - null/undefined: false
12428
+ */
12429
+ function isFilledValue(value) {
12430
+ if (isNil$1(value)) return false;
12431
+ switch (typeof value) {
12432
+ case "number":
12433
+ case "boolean": return true;
12434
+ case "string": return value.trim() !== "";
12435
+ default:
12436
+ if (isEmpty(value)) return false;
12437
+ if (Array.isArray(value)) return value.every(isFilledValue);
12438
+ return Object.values(value).every(isFilledValue);
12439
+ }
12440
+ }
12441
+ const KNOWN_LEAF_KEYS = /* @__PURE__ */ new Set([
12442
+ "n",
12443
+ "x",
12444
+ "rhs",
12445
+ "type",
12446
+ "value",
12447
+ "column",
12448
+ "minDiff",
12449
+ "maxEdits",
12450
+ "wildcard",
12451
+ "replacement",
12452
+ "substitutionsOnly"
12453
+ ]);
12454
+ /** Required fields per leaf type. Optional fields (e.g. minDiff, maxEdits) excluded. */
12455
+ const REQUIRED_KEYS_BY_TYPE = {
12456
+ isNA: ["column"],
12457
+ isNotNA: ["column"],
12458
+ ifNa: ["column", "replacement"],
12459
+ patternEquals: ["column", "value"],
12460
+ patternNotEquals: ["column", "value"],
12461
+ patternContainSubsequence: ["column", "value"],
12462
+ patternNotContainSubsequence: ["column", "value"],
12463
+ patternMatchesRegularExpression: ["column", "value"],
12464
+ patternFuzzyContainSubsequence: ["column", "value"],
12465
+ inSet: ["column", "value"],
12466
+ notInSet: ["column", "value"],
12467
+ topN: ["column", "n"],
12468
+ bottomN: ["column", "n"],
12469
+ equal: ["column", "x"],
12470
+ notEqual: ["column", "x"],
12471
+ lessThan: ["column", "x"],
12472
+ greaterThan: ["column", "x"],
12473
+ lessThanOrEqual: ["column", "x"],
12474
+ greaterThanOrEqual: ["column", "x"],
12475
+ equalToColumn: ["column", "rhs"],
12476
+ lessThanColumn: ["column", "rhs"],
12477
+ greaterThanColumn: ["column", "rhs"],
12478
+ lessThanColumnOrEqual: ["column", "rhs"],
12479
+ greaterThanColumnOrEqual: ["column", "rhs"]
12480
+ };
12481
+ //#endregion
12482
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/state-migration.js
12483
+ /** Upgrade PlDataTableStateV2 to the latest version */
12484
+ function upgradePlDataTableStateV2(state) {
12485
+ if (!state) return createPlDataTableStateV2();
12486
+ if (!("version" in state)) state = createPlDataTableStateV2();
12487
+ if (state.version === 2) state = {
12488
+ version: 3,
12489
+ stateCache: state.stateCache.map((entry) => ({
12490
+ ...entry,
12491
+ filtersState: []
12492
+ })),
12493
+ pTableParams: createDefaultPTableParamsV7()
12494
+ };
12495
+ if (state.version === 3) state = createPlDataTableStateV2();
12496
+ if (state.version === 4) state = migrateV4toV6(state);
12497
+ if (state.version === 5) state = migrateV5toV6(state);
12498
+ if (state.version === 6) state = migrateV6toV7(state);
12499
+ if (state.version === 7) state = migrateV7toV8(state);
12500
+ return state;
12501
+ }
12502
+ /** Migrate v5 to v6: unwrap `{source, labeled}` colIds in gridState. */
12503
+ function migrateV5toV6(state) {
12504
+ return {
12505
+ version: 6,
12506
+ stateCache: state.stateCache.map((entry) => ({
12507
+ ...entry,
12508
+ gridState: unwrapV5GridState(entry.gridState)
12509
+ })),
12510
+ pTableParams: createDefaultPTableParamsV7()
12511
+ };
12512
+ }
12513
+ /** Convert v5 wrapped colId JSON to bare PTableColumnSpec JSON, taking `.source`.
12514
+ * gridState colIds may include the row-number sentinel (a JSON-stringified
12515
+ * literal, not a wrapped spec) — those pass through unchanged. */
12516
+ function unwrapV5ColId(json) {
12517
+ const parsed = parseJsonSafely(json);
12518
+ return !isNil(parsed) && typeof parsed === "object" && "source" in parsed ? canonicalizeJson(parsed.source) : json;
12519
+ }
12520
+ function unwrapV5GridState(gridState) {
12521
+ const unwrapAs = (json) => unwrapV5ColId(json);
12522
+ return {
12523
+ columnOrder: gridState.columnOrder ? { orderedColIds: gridState.columnOrder.orderedColIds.map(unwrapAs) } : void 0,
12524
+ sort: gridState.sort ? { sortModel: gridState.sort.sortModel.map((s) => ({
12525
+ colId: unwrapAs(s.colId),
12526
+ sort: s.sort
12527
+ })) } : void 0,
12528
+ columnVisibility: gridState.columnVisibility ? { hiddenColIds: gridState.columnVisibility.hiddenColIds.map(unwrapAs) } : void 0
12529
+ };
12530
+ }
12531
+ /** Migrate v6 to v7: rewrite each colId from a full PTableColumnSpec to its
12532
+ * compact PTableColumnId (drops annotations/spec body, ~16× smaller per column). */
12533
+ function migrateV6toV7(state) {
12534
+ return {
12535
+ version: 7,
12536
+ stateCache: state.stateCache.map((entry) => ({
12537
+ ...entry,
12538
+ gridState: shrinkV6GridState(entry.gridState)
12539
+ })),
12540
+ pTableParams: state.pTableParams
12541
+ };
12542
+ }
12543
+ /** Convert a v6 fat colId (canonicalized PTableColumnSpec) to a v7 compact colId
12544
+ * (canonicalized PTableColumnId). The row-number sentinel is a string literal,
12545
+ * not a spec — pass it through unchanged. */
12546
+ function shrinkV6ColId(json) {
12547
+ const parsed = parseJsonSafely(json);
12548
+ if (!isNil(parsed) && typeof parsed === "object" && "type" in parsed && "id" in parsed) return canonicalizeJson(getPTableColumnId(parsed));
12549
+ return json;
12550
+ }
12551
+ function shrinkV6GridState(gridState) {
12552
+ return {
12553
+ columnOrder: gridState.columnOrder ? { orderedColIds: gridState.columnOrder.orderedColIds.map(shrinkV6ColId) } : void 0,
12554
+ sort: gridState.sort ? { sortModel: gridState.sort.sortModel.map((s) => ({
12555
+ colId: shrinkV6ColId(s.colId),
12556
+ sort: s.sort
12557
+ })) } : void 0,
12558
+ columnVisibility: gridState.columnVisibility ? { hiddenColIds: gridState.columnVisibility.hiddenColIds.map(shrinkV6ColId) } : void 0
12559
+ };
12560
+ }
12561
+ /** Migrate v4 state to v6: convert per-column filters to tree-based format (skips v5). */
12562
+ function migrateV4toV6(state) {
12563
+ let idCounter = 0;
12564
+ const nextId = () => ++idCounter;
12565
+ const migratedCache = state.stateCache.map((entry) => {
12566
+ const leaves = [];
12567
+ for (const f of entry.filtersState) if (f.filter !== null && !f.filter.disabled) leaves.push(migrateTableFilter(canonicalizeJson(f.id), f.filter.value, nextId));
12568
+ const filtersState = leaves.length > 0 ? {
12569
+ id: nextId(),
12570
+ type: "and",
12571
+ filters: leaves
12572
+ } : null;
12573
+ return {
12574
+ sourceId: entry.sourceId,
12575
+ gridState: entry.gridState,
12576
+ sheetsState: entry.sheetsState,
12577
+ filtersState,
12578
+ defaultFiltersState: null
12579
+ };
12580
+ });
12581
+ const oldSourceId = state.pTableParams.sourceId;
12582
+ const currentCache = oldSourceId ? migratedCache.find((e) => e.sourceId === oldSourceId) : void 0;
12583
+ return {
12584
+ version: 6,
12585
+ stateCache: migratedCache,
12586
+ pTableParams: currentCache && oldSourceId ? {
12587
+ sourceId: oldSourceId,
12588
+ hiddenColIds: state.pTableParams.hiddenColIds?.map((id) => ({
12589
+ type: "column",
12590
+ id
12591
+ })) ?? null,
12592
+ filters: distillFilterSpec(currentCache.filtersState),
12593
+ defaultFilters: null,
12594
+ sorting: state.pTableParams.sorting
12595
+ } : createDefaultPTableParamsV7()
12596
+ };
12597
+ }
12598
+ /** Migrate a single per-column PlTableFilter to a v7-form tree node (legacy
12599
+ * string column ids). v7 → v8 later converts these to object form. */
12600
+ function migrateTableFilter(column, filter, nextId) {
12601
+ const id = nextId();
12602
+ switch (filter.type) {
12603
+ case "isNA": return {
12604
+ id,
12605
+ type: "isNA",
12606
+ column
12607
+ };
12608
+ case "isNotNA": return {
12609
+ id,
12610
+ type: "isNotNA",
12611
+ column
12612
+ };
12613
+ case "number_equals": return {
12614
+ id,
12615
+ type: "equal",
12616
+ column,
12617
+ x: filter.reference
12618
+ };
12619
+ case "number_notEquals": return {
12620
+ id,
12621
+ type: "notEqual",
12622
+ column,
12623
+ x: filter.reference
12624
+ };
12625
+ case "number_greaterThan": return {
12626
+ id,
12627
+ type: "greaterThan",
12628
+ column,
12629
+ x: filter.reference
12630
+ };
12631
+ case "number_greaterThanOrEqualTo": return {
12632
+ id,
12633
+ type: "greaterThanOrEqual",
12634
+ column,
12635
+ x: filter.reference
12636
+ };
12637
+ case "number_lessThan": return {
12638
+ id,
12639
+ type: "lessThan",
12640
+ column,
12641
+ x: filter.reference
12642
+ };
12643
+ case "number_lessThanOrEqualTo": return {
12644
+ id,
12645
+ type: "lessThanOrEqual",
12646
+ column,
12647
+ x: filter.reference
12648
+ };
12649
+ case "number_between": return {
12650
+ id,
12651
+ type: "and",
12652
+ filters: [filter.includeLowerBound ? {
12653
+ id: nextId(),
12654
+ type: "greaterThanOrEqual",
12655
+ column,
12656
+ x: filter.lowerBound
12657
+ } : {
12658
+ id: nextId(),
12659
+ type: "greaterThan",
12660
+ column,
12661
+ x: filter.lowerBound
12662
+ }, filter.includeUpperBound ? {
12663
+ id: nextId(),
12664
+ type: "lessThanOrEqual",
12665
+ column,
12666
+ x: filter.upperBound
12667
+ } : {
12668
+ id: nextId(),
12669
+ type: "lessThan",
12670
+ column,
12671
+ x: filter.upperBound
12672
+ }]
12673
+ };
12674
+ case "string_equals": return {
12675
+ id,
12676
+ type: "patternEquals",
12677
+ column,
12678
+ value: filter.reference
12679
+ };
12680
+ case "string_notEquals": return {
12681
+ id,
12682
+ type: "patternNotEquals",
12683
+ column,
12684
+ value: filter.reference
12685
+ };
12686
+ case "string_contains": return {
12687
+ id,
12688
+ type: "patternContainSubsequence",
12689
+ column,
12690
+ value: filter.reference
12691
+ };
12692
+ case "string_doesNotContain": return {
12693
+ id,
12694
+ type: "patternNotContainSubsequence",
12695
+ column,
12696
+ value: filter.reference
12697
+ };
12698
+ case "string_matches": return {
12699
+ id,
12700
+ type: "patternMatchesRegularExpression",
12701
+ column,
12702
+ value: filter.reference
12703
+ };
12704
+ case "string_doesNotMatch": return {
12705
+ id,
12706
+ type: "not",
12707
+ filter: {
12708
+ id: nextId(),
12709
+ type: "patternMatchesRegularExpression",
12710
+ column,
12711
+ value: filter.reference
12712
+ }
12713
+ };
12714
+ case "string_containsFuzzyMatch": return {
12715
+ id,
12716
+ type: "patternFuzzyContainSubsequence",
12717
+ column,
12718
+ value: filter.reference,
12719
+ maxEdits: filter.maxEdits,
12720
+ substitutionsOnly: filter.substitutionsOnly,
12721
+ ...filter.wildcard !== void 0 ? { wildcard: filter.wildcard } : {}
12722
+ };
12723
+ }
12724
+ }
12725
+ /** Default pTableParams in the v7 shape (sorting: []). Used by intermediate
12726
+ * migration steps that produce v6/v7 state before the v7 → v8 conversion. */
12727
+ function createDefaultPTableParamsV7() {
12728
+ return {
12729
+ sourceId: null,
12730
+ hiddenColIds: null,
12731
+ filters: null,
12732
+ defaultFilters: null,
12733
+ sorting: []
12734
+ };
12735
+ }
12736
+ function createDefaultPTableParams() {
12737
+ return {
12738
+ sourceId: null,
12739
+ hiddenColIds: null,
12740
+ filters: null,
12741
+ defaultFilters: null,
12742
+ sorting: null
11458
12743
  };
11459
12744
  }
12745
+ function createPlDataTableStateV2() {
12746
+ return {
12747
+ version: 8,
12748
+ stateCache: [],
12749
+ pTableParams: createDefaultPTableParams()
12750
+ };
12751
+ }
12752
+ function migrateV7toV8(state) {
12753
+ const newCache = state.stateCache.map((entry) => ({
12754
+ sourceId: entry.sourceId,
12755
+ gridState: entry.gridState,
12756
+ sheetsState: entry.sheetsState,
12757
+ filtersState: convertFiltersWithMeta(entry.filtersState),
12758
+ defaultFiltersState: convertFiltersWithMeta(entry.defaultFiltersState),
12759
+ searchString: entry.searchString
12760
+ }));
12761
+ const params = state.pTableParams;
12762
+ let pTableParams;
12763
+ if (params.sourceId === null) pTableParams = createDefaultPTableParams();
12764
+ else pTableParams = {
12765
+ sourceId: params.sourceId,
12766
+ hiddenColIds: params.hiddenColIds,
12767
+ sorting: params.sorting.length === 0 ? null : params.sorting,
12768
+ filters: convertFiltersPlain(params.filters),
12769
+ defaultFilters: convertFiltersPlain(params.defaultFilters)
12770
+ };
12771
+ return {
12772
+ version: 8,
12773
+ stateCache: newCache,
12774
+ pTableParams
12775
+ };
12776
+ }
12777
+ function convertFiltersWithMeta(node) {
12778
+ if (node === null) return null;
12779
+ const result = pruneFilterNode(node);
12780
+ if (result === void 0) return null;
12781
+ return result;
12782
+ }
12783
+ function convertFiltersPlain(node) {
12784
+ if (node === null) return null;
12785
+ const result = pruneFilterNode(node);
12786
+ if (result === void 0) return null;
12787
+ return result;
12788
+ }
12789
+ /** Recursively converts and prunes a legacy v7 filter tree. Preserves meta
12790
+ * fields (id/isExpanded/source/isSuppressed) on non-leaf nodes. Returns
12791
+ * `undefined` when the subtree is empty after pruning. */
12792
+ function pruneFilterNode(node) {
12793
+ if (!node || typeof node !== "object") return void 0;
12794
+ const n = node;
12795
+ if (n.type === "and" || n.type === "or") {
12796
+ const kept = (n.filters ?? []).map((f) => pruneFilterNode(f)).filter((f) => f !== void 0);
12797
+ if (kept.length === 0) return void 0;
12798
+ return {
12799
+ ...n,
12800
+ type: n.type,
12801
+ filters: kept
12802
+ };
12803
+ }
12804
+ if (n.type === "not") {
12805
+ const inner = pruneFilterNode(n.filter);
12806
+ if (inner === void 0) return void 0;
12807
+ return {
12808
+ ...n,
12809
+ type: "not",
12810
+ filter: inner
12811
+ };
12812
+ }
12813
+ return convertLegacyLeaf(n);
12814
+ }
12815
+ function convertLegacyLeaf(leaf) {
12816
+ if (leaf.type === void 0) return leaf;
12817
+ const result = { ...leaf };
12818
+ if ("column" in result) {
12819
+ const c = parseLegacyLeafColumn(result.column);
12820
+ if (c === void 0) return void 0;
12821
+ result.column = c;
12822
+ }
12823
+ if ("rhs" in result) {
12824
+ const c = parseLegacyLeafColumn(result.rhs);
12825
+ if (c === void 0) return void 0;
12826
+ result.rhs = c;
12827
+ }
12828
+ return result;
12829
+ }
12830
+ function parseLegacyLeafColumn(s) {
12831
+ if (typeof s !== "string") return void 0;
12832
+ const parsed = parseJsonSafely(s);
12833
+ if (!parsed || typeof parsed !== "object") return void 0;
12834
+ if (!("type" in parsed) || !("id" in parsed)) return void 0;
12835
+ const t = parsed.type;
12836
+ if (t !== "axis" && t !== "column") return void 0;
12837
+ return parsed;
12838
+ }
12839
+ //#endregion
12840
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/utils.js
12841
+ /** Adapt a {@link ColumnRecipe} to the plain {@link RuleColumn} shape. */
12842
+ function toRuleColumn(col) {
12843
+ return {
12844
+ id: extractPObjectId(col.id),
12845
+ spec: col.getSpec()
12846
+ };
12847
+ }
12848
+ /** Check if column should be omitted from the table */
12849
+ function isColumnHidden(spec) {
12850
+ return readAnnotation(spec, Annotation.Table.Visibility) === "hidden";
12851
+ }
12852
+ /** Check if column is hidden by default */
12853
+ function isColumnOptional(spec) {
12854
+ return readAnnotation(spec, Annotation.Table.Visibility) === "optional";
12855
+ }
12856
+ /** Get effective visibility for a column. Rule map lookup first, then annotation fallback. */
12857
+ function getEffectiveVisibility(col, visibilityByColId) {
12858
+ const rule = visibilityByColId?.get(col.id);
12859
+ if (rule !== void 0) return rule.visibility;
12860
+ if (isColumnHidden(col.spec)) return "hidden";
12861
+ if (isColumnOptional(col.spec)) return "optional";
12862
+ }
12863
+ /** Get ordering priority for a column. Rule map lookup first, then annotation fallback. */
12864
+ function getOrderPriority(col, orderByColId) {
12865
+ const rule = orderByColId?.get(col.id);
12866
+ if (rule !== void 0) return rule.priority;
12867
+ const annotation = Number(readAnnotation(col.spec, Annotation.Table.OrderPriority));
12868
+ return isNaN(annotation) ? void 0 : annotation;
12869
+ }
12870
+ /**
12871
+ * Evaluate display rules against a set of columns and return a map of `colId → winning rule`
12872
+ * (first-match-wins, preserving original rule order).
12873
+ *
12874
+ * Predicate-based rules (`ColumnMatcher`) are evaluated directly on the spec.
12875
+ * Selector-based rules (`ColumnSelector`) are matched via the
12876
+ * `columnsCollection` service — the inline column ids must be resolvable in
12877
+ * the active render ctx for the host to read their specs.
12878
+ */
12879
+ function evaluateRules(rules, columns) {
12880
+ const result = /* @__PURE__ */ new Map();
12881
+ if (rules.length === 0 || columns.length === 0) return result;
12882
+ const selectorRules = rules.filter((rule) => typeof rule.match !== "function");
12883
+ const selectorHitsByRule = /* @__PURE__ */ new Map();
12884
+ if (selectorRules.length > 0) {
12885
+ const baseCollection = ColumnsCollection([{
12886
+ columns: uniqBy(columns, (col) => col.id),
12887
+ isFinal: true
12888
+ }]);
12889
+ for (const rule of selectorRules) {
12890
+ const hitIds = baseCollection.filter({ include: rule.match }).getColumnIds();
12891
+ if (hitIds.length === 0) continue;
12892
+ selectorHitsByRule.set(rule, new Set(hitIds.map((id) => extractPObjectId(id))));
12893
+ }
12894
+ }
12895
+ for (const col of columns) {
12896
+ const colKey = extractPObjectId(col.id);
12897
+ for (const rule of rules) if (selectorHitsByRule.get(rule)?.has(colKey) ?? false) {
12898
+ result.set(colKey, rule);
12899
+ break;
12900
+ }
12901
+ }
12902
+ return result;
12903
+ }
12904
+ /**
12905
+ * Build a sidecar map `columnId → AnnotationDataStatus` derived from each
12906
+ * recipe's own status. This is *rendering* metadata — kept out of the spec
12907
+ * so it cannot perturb column identity (id-bearing spec overrides would
12908
+ * diverge the visible PTable's column ids from the full table / pframe).
12909
+ *
12910
+ * Mapping `ColumnFieldStatus` × actual byte-presence → `AnnotationDataStatus`:
12911
+ * - `absent` → `"absent"`
12912
+ * - `resolving` → `"computing"`
12913
+ * - `present` + `hasColumnData()` → `"ready"`
12914
+ * - `present` + no bytes yet → `"computing"`
12915
+ *
12916
+ * Intentionally scoped to visible columns — the probe is meaningful only for
12917
+ * what the user will actually see.
12918
+ */
12919
+ function buildDataStatusMap(columns, opts = {}) {
12920
+ return columns.reduce((acc, c) => (acc[c.id] = deriveDataStatus(c, opts), acc), {});
12921
+ }
12922
+ function deriveDataStatus(column, opts) {
12923
+ const field = column.getDataStatus();
12924
+ if (field === "absent") return "absent";
12925
+ if (field === "resolving") return "computing";
12926
+ return hasColumnData(column, opts) ? "ready" : "computing";
12927
+ }
12928
+ /** Derive labels for all table elements: columns via deriveDistinctLabels, axes from label columns. */
12929
+ function deriveAllLabels(options) {
12930
+ const { columns, deriveLabelsOptions } = options;
12931
+ return deriveDistinctLabels(columns.map((c) => ({
12932
+ spec: c.spec,
12933
+ linkerPath: c.linkerPath?.map((step) => ({ spec: step.linker.spec })),
12934
+ qualifications: c.qualifications
12935
+ })), deriveLabelsOptions).reduce((acc, label, index) => (acc[columns[index].id] = label, acc), {});
12936
+ }
12937
+ //#endregion
12938
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js
12939
+ /**
12940
+ * Assemble a ptable def directly from recipes. Each secondary recipe is its own
12941
+ * outer-joined subtree: `getQuery()` encodes its linker chain, and its
12942
+ * hit-/queries-qualifications are derived on the spot via {@link hitQualifications}
12943
+ * / {@link queriesQualifications} — no pre-extracted DTO. Bare leaves yield empty
12944
+ * qualifications, so plain {@link ColumnRecipe} arrays (e.g. label columns) work
12945
+ * unchanged.
12946
+ */
12947
+ function createPTableDefV3(params) {
12948
+ let query = {
12949
+ type: params.primaryJoinType === "inner" ? "innerJoin" : "fullJoin",
12950
+ entries: params.primary.map((c) => columnToJoinEntry(c, []))
12951
+ };
12952
+ if (params.secondary.length > 0) query = {
12953
+ type: "outerJoin",
12954
+ primary: {
12955
+ entry: query,
12956
+ qualifications: params.secondary.flatMap((s) => {
12957
+ const quals = queriesQualifications(s);
12958
+ return params.primary.flatMap((p) => quals[p.id] ?? []);
12959
+ })
12960
+ },
12961
+ secondary: params.secondary.map((c) => columnToJoinEntry(c, hitQualifications(c)))
12962
+ };
12963
+ if (!isNil(params.filters)) {
12964
+ const nonEmpty = distillFilterSpec(params.filters);
12965
+ if (!isNil(nonEmpty)) {
12966
+ const pridicate = filterSpecToSpecQueryExpr(nonEmpty);
12967
+ if (!isBooleanExpression(pridicate)) throw new Error(`Filter conversion produced a non-boolean expression (got type "${pridicate.type}"), expected a boolean predicate for query filtering`);
12968
+ query = {
12969
+ type: "filter",
12970
+ input: query,
12971
+ predicate: pridicate
12972
+ };
12973
+ }
12974
+ }
12975
+ if (!isNil(params.sorting) && params.sorting.length > 0) query = {
12976
+ type: "sort",
12977
+ input: query,
12978
+ sortBy: params.sorting.map((s) => ({
12979
+ expression: columnIdToExpr(s.column),
12980
+ ascending: s.ascending,
12981
+ nullsFirst: s.naAndAbsentAreLeastValues
12982
+ }))
12983
+ };
12984
+ return { query };
12985
+ }
12986
+ function columnIdToExpr(col) {
12987
+ return col.type === "axis" ? {
12988
+ type: "axisRef",
12989
+ value: col.id
12990
+ } : {
12991
+ type: "columnRef",
12992
+ value: col.id
12993
+ };
12994
+ }
12995
+ function columnToJoinEntry(col, qualifications) {
12996
+ return {
12997
+ entry: col.getQuery(),
12998
+ qualifications
12999
+ };
13000
+ }
13001
+ //#endregion
13002
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/columnResolver.js
13003
+ function createColumnResolver(columns) {
13004
+ const axisIds = [];
13005
+ for (const c of columns) for (const ax of c.getSpec().axesSpec) axisIds.push(getAxisId(ax));
13006
+ const byFullId = /* @__PURE__ */ new Map();
13007
+ const byPObjectId = /* @__PURE__ */ new Map();
13008
+ for (const c of columns) {
13009
+ byFullId.set(c.id, c);
13010
+ const pid = extractPObjectId(c.id);
13011
+ if (!byPObjectId.has(pid)) byPObjectId.set(pid, c);
13012
+ }
13013
+ return (ref) => {
13014
+ if (ref.type === "axis") return axisIds.some((a) => matchAxisId(ref.id, a)) ? ref : void 0;
13015
+ const hit = byFullId.get(ref.id) ?? byPObjectId.get(extractPObjectId(ref.id));
13016
+ if (hit === void 0) return void 0;
13017
+ return {
13018
+ type: "column",
13019
+ id: hit.id
13020
+ };
13021
+ };
13022
+ }
13023
+ //#endregion
13024
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/discoverColumns.js
13025
+ /**
13026
+ * Discover columns from sources/anchors and split them into primary
13027
+ * (direct anchor hits — zero-hop, query is a bare column) and secondary
13028
+ * (reached via a linker chain, query carries a join).
13029
+ */
13030
+ function discoverTableColumns(ctx, options) {
13031
+ const discoveredColumns = ColumnsCollection(options.sources, { ctx: ctx.ctx }).discover({
13032
+ ...options.selector,
13033
+ anchors: options.anchors
13034
+ }).getColumns();
13035
+ const primary = [];
13036
+ const secondary = [];
13037
+ for (const col of discoveredColumns) if (hasSingleDataColumn(col)) primary.push(col);
13038
+ else secondary.push(col);
13039
+ return {
13040
+ primary,
13041
+ secondary
13042
+ };
13043
+ }
13044
+ /**
13045
+ * Discover label columns matching the axes of the given value columns from
13046
+ * ctx providers. Returns a list of label {@link ColumnRecipe}s.
13047
+ *
13048
+ * Primary columns are used as anchors for axis-aware label discovery.
13049
+ * `maxHops` is taken from the longest linker chain present in `columns`.
13050
+ */
13051
+ function discoverLabelColumns(ctx, primary) {
13052
+ if (primary.length === 0) return [];
13053
+ const axes = primary.flatMap((col) => col.getSpec().axesSpec);
13054
+ return ColumnsCollection(void 0, { ctx: ctx.ctx }).discover({
13055
+ include: axes.map((a) => ({
13056
+ name: {
13057
+ type: "exact",
13058
+ value: PColumnName.Label
13059
+ },
13060
+ axes: [{ name: {
13061
+ type: "exact",
13062
+ value: a.name
13063
+ } }]
13064
+ })),
13065
+ anchors: Object.fromEntries(primary.map((col, i) => [`anchor_${i}`, col.getSpec()])),
13066
+ maxHops: 0
13067
+ }).getColumns();
13068
+ }
13069
+ //#endregion
13070
+ //#region ../node_modules/.pnpm/@platforma-sdk+model@1.84.3/node_modules/@platforma-sdk/model/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js
13071
+ function createPlDataTableV3(ctx, options) {
13072
+ const state = upgradePlDataTableStateV2(options.tableState);
13073
+ const primaryJoinType = options.primaryJoinType ?? "full";
13074
+ const resolved = resolveInputColumns(ctx, options);
13075
+ if (resolved === void 0) return void 0;
13076
+ const { primary, secondary } = resolved;
13077
+ if (primary.length === 0) return void 0;
13078
+ const { direct, linked } = splitByTopology(secondary);
13079
+ const derivedLabels = deriveAllLabels({
13080
+ columns: [...primary, ...secondary].filter((c) => !isColumnHidden(c.getSpec())).map(toLabelableColumn),
13081
+ deriveLabelsOptions: {
13082
+ includeNativeLabel: true,
13083
+ ...options.labelsOptions
13084
+ }
13085
+ });
13086
+ const allColumnsForRules = [
13087
+ ...primary,
13088
+ ...direct,
13089
+ ...linked,
13090
+ ...collectLinkerSnapshots(linked)
13091
+ ];
13092
+ const visibilityByColId = evaluateRules(options.displayOptions?.visibility ?? [], allColumnsForRules);
13093
+ const orderByColId = evaluateRules(options.displayOptions?.ordering ?? [], allColumnsForRules);
13094
+ const resolver = createColumnResolver([
13095
+ ...primary,
13096
+ ...direct,
13097
+ ...linked.flatMap((lc) => [...collectLinkerColumns(lc), lc])
13098
+ ]);
13099
+ const remapedDefaultFilters = remapFilterColumnIds(options.filters, resolver);
13100
+ const filters = filterFilters(concatFilters(state.pTableParams.filters, state.pTableParams.defaultFilters ?? remapedDefaultFilters), resolver);
13101
+ const sorting = filterSorting(resolveSorting(state.pTableParams.sorting, remapSortingColumnIds(options.sorting, resolver)), resolver);
13102
+ const fullDef = createPTableDefV3({
13103
+ primaryJoinType,
13104
+ primary,
13105
+ secondary: [...direct, ...linked],
13106
+ filters,
13107
+ sorting
13108
+ });
13109
+ const fullHandle = ctx.createPTableV2(fullDef);
13110
+ const pframeHandle = ctx.createPFrame(uniq([
13111
+ ...primary.map((v) => extractPObjectId(v.id)),
13112
+ ...direct.map((v) => extractPObjectId(v.id)),
13113
+ ...linked.map((v) => extractPObjectId(v.id))
13114
+ ]));
13115
+ const hiddenSpecs = state.pTableParams.hiddenColIds;
13116
+ const hiddenColumnIds = computeHiddenColumns({
13117
+ columns: [
13118
+ ...primary,
13119
+ ...direct,
13120
+ ...linked
13121
+ ],
13122
+ visibilityByColId,
13123
+ sorting,
13124
+ filters,
13125
+ hiddenSpecs
13126
+ });
13127
+ const visible = {
13128
+ primary,
13129
+ direct: direct.filter((c) => !hiddenColumnIds.has(c.id)),
13130
+ linked: linked.filter((c) => !hiddenColumnIds.has(c.id))
13131
+ };
13132
+ const visibleDef = createPTableDefV3({
13133
+ primaryJoinType,
13134
+ primary,
13135
+ secondary: [...visible.direct, ...visible.linked],
13136
+ filters,
13137
+ sorting
13138
+ });
13139
+ const visibleHandle = ctx.createPTableV2(visibleDef);
13140
+ const columnsMeta = buildColumnsMeta({
13141
+ fullColumns: [
13142
+ ...primary,
13143
+ ...direct,
13144
+ ...linked
13145
+ ],
13146
+ visibleColumns: [
13147
+ ...visible.primary,
13148
+ ...visible.direct,
13149
+ ...visible.linked
13150
+ ],
13151
+ primaryColumns: primary,
13152
+ derivedLabels,
13153
+ visibilityByColId,
13154
+ orderByColId
13155
+ });
13156
+ return {
13157
+ sourceId: state.pTableParams.sourceId,
13158
+ fullTableHandle: fullHandle,
13159
+ fullPframeHandle: pframeHandle,
13160
+ visibleTableHandle: visibleHandle,
13161
+ defaultFilters: remapedDefaultFilters,
13162
+ columnsMeta
13163
+ };
13164
+ }
13165
+ /** Normalize either option branch into a {primary, secondary} pair of recipes. */
13166
+ function resolveInputColumns(ctx, options) {
13167
+ if ("primaryColumns" in options) {
13168
+ const primary = options.primaryColumns;
13169
+ const secondary = options.columns ?? [];
13170
+ const labels = discoverLabelColumns(ctx, primary);
13171
+ const primaryIds = new Set(primary.map((c) => c.id));
13172
+ return {
13173
+ primary,
13174
+ secondary: dedupColumns([...secondary, ...labels].filter((c) => !primaryIds.has(c.id)), (c) => c.id, (c) => c.getSpec())
13175
+ };
13176
+ }
13177
+ if (isPlainObject$1(options.columns)) return discoverTableColumns(ctx, options.columns);
13178
+ }
13179
+ /** Split secondary recipes by query topology: leaves (no linker chain) vs joined. */
13180
+ function splitByTopology(columns) {
13181
+ const direct = [];
13182
+ const linked = [];
13183
+ for (const c of columns) if (hasSingleDataColumn(c)) direct.push(c);
13184
+ else linked.push(c);
13185
+ return {
13186
+ direct,
13187
+ linked
13188
+ };
13189
+ }
13190
+ /** All linker recipes across the given linked columns, deduped by id. */
13191
+ function collectLinkerSnapshots(linked) {
13192
+ return uniqueBy(linked.flatMap((c) => collectLinkerColumns(c)), (c) => c.id);
13193
+ }
13194
+ function toLabelableColumn(col) {
13195
+ return {
13196
+ id: col.id,
13197
+ spec: col.getSpec(),
13198
+ linkerPath: collectLinkerColumns(col).map((linker) => ({ linker: { spec: linker.getSpec() } })),
13199
+ qualifications: {
13200
+ forHit: [...hitQualifications(col)],
13201
+ forQueries: queriesQualifications(col)
13202
+ }
13203
+ };
13204
+ }
13205
+ /**
13206
+ * Compute display metadata as a sidecar keyed by each emitted column's
13207
+ * `ColumnUniversalId` (and axis `AxisId`), instead of baking it into the specs
13208
+ * via `withSpecs`. Spec overrides change a recipe's id, so the same physical
13209
+ * column reached two ways would diverge into two ids and render twice; keeping
13210
+ * meta out of the spec preserves identity and lets dedup collapse such cases.
13211
+ * The UI overlays this onto the engine-emitted specs at render time.
13212
+ */
13213
+ function buildColumnsMeta(params) {
13214
+ const { fullColumns, visibleColumns, primaryColumns, derivedLabels } = params;
13215
+ const { visibilityByColId, orderByColId } = params;
13216
+ const visibleStatus = buildDataStatusMap(visibleColumns);
13217
+ const columns = fullColumns.reduce((acc, c) => {
13218
+ const rc = toRuleColumn(c);
13219
+ acc[c.id] = {
13220
+ label: derivedLabels[c.id],
13221
+ visibility: getEffectiveVisibility(rc, visibilityByColId),
13222
+ order: getOrderPriority(rc, orderByColId),
13223
+ status: visibleStatus[c.id]
13224
+ };
13225
+ return acc;
13226
+ }, {});
13227
+ const primaryAxisKeys = new Set(primaryColumns.flatMap((c) => c.getSpec().axesSpec.map((a) => canonicalizeAxisId(a))));
13228
+ return {
13229
+ columns,
13230
+ axes: fullColumns.reduce((acc, c) => c.getSpec().axesSpec.reduce((inner, ax) => {
13231
+ const key = canonicalizeAxisId(ax);
13232
+ if (inner[key] === void 0) inner[key] = { hidden: !primaryAxisKeys.has(key) };
13233
+ return inner;
13234
+ }, acc), {})
13235
+ };
13236
+ }
13237
+ /** Drop filter leaves whose column references cannot be resolved; rewrite the
13238
+ * resolvable ones through the resolver. Prune empty and/or/not groups. */
13239
+ function filterFilters(filters, resolver) {
13240
+ if (isNil$1(filters)) return filters;
13241
+ const rewriteLeaf = (leaf) => {
13242
+ if (leaf.type === void 0) return leaf;
13243
+ const result = { ...leaf };
13244
+ if ("column" in result) {
13245
+ const c = resolver(result.column);
13246
+ if (isNil$1(c)) return void 0;
13247
+ result.column = c;
13248
+ }
13249
+ if ("rhs" in result) {
13250
+ const c = resolver(result.rhs);
13251
+ if (isNil$1(c)) return void 0;
13252
+ result.rhs = c;
13253
+ }
13254
+ return result;
13255
+ };
13256
+ const prune = (node) => {
13257
+ if (node.type === "and" || node.type === "or") {
13258
+ const kept = node.filters.map((f) => prune(f)).filter((f) => !isNil$1(f));
13259
+ if (kept.length === 0) return void 0;
13260
+ return {
13261
+ type: node.type,
13262
+ filters: kept
13263
+ };
13264
+ }
13265
+ if (node.type === "not") {
13266
+ const inner = prune(node.filter);
13267
+ return isNil$1(inner) ? void 0 : {
13268
+ type: "not",
13269
+ filter: inner
13270
+ };
13271
+ }
13272
+ return rewriteLeaf(node);
13273
+ };
13274
+ return prune(filters);
13275
+ }
13276
+ /** Merge two filter trees into one AND-combined tree. Returns the non-nil one if the other is nil.
13277
+ * Exported for unit testing. */
13278
+ function concatFilters(a, b) {
13279
+ if (isNil$1(a)) return b;
13280
+ if (isNil$1(b)) return a;
13281
+ const operands = (f) => f.type === "and" ? f.filters : [f];
13282
+ return {
13283
+ type: "and",
13284
+ filters: [...operands(a), ...operands(b)]
13285
+ };
13286
+ }
13287
+ /** Pick user sorting from state if set, otherwise fall back to options default.
13288
+ * null = user has not touched sorting → use default;
13289
+ * [] = user has explicitly cleared sorting → no sorting (default ignored). */
13290
+ function resolveSorting(userSorting, defaultSorting) {
13291
+ return (isNil$1(userSorting) ? defaultSorting : userSorting) ?? [];
13292
+ }
13293
+ /** Rewrite sorting entries through the resolver; drop those that fail to resolve. */
13294
+ function filterSorting(sorting, resolver) {
13295
+ return sorting.flatMap((s) => {
13296
+ const col = resolver(s.column);
13297
+ return isNil$1(col) ? [] : [{
13298
+ ...s,
13299
+ column: col
13300
+ }];
13301
+ });
13302
+ }
13303
+ /** Determine which columns should be hidden based on state or optional-column defaults.
13304
+ * Keyed by the recipe's logical {@link ColumnUniversalId} (rich) — variants of
13305
+ * the same physical column are independently visible/hidden. */
13306
+ function computeHiddenColumns(params) {
13307
+ const { columns, visibilityByColId, sorting, filters, hiddenSpecs } = params;
13308
+ const visibilityOf = (c) => getEffectiveVisibility(toRuleColumn(c), visibilityByColId);
13309
+ const alwaysHidden = columns.filter((c) => visibilityOf(c) === "hidden").map((c) => c.id);
13310
+ const optionalHidden = !isNil$1(hiddenSpecs) ? hiddenSpecs.filter((s) => s.type === "column").map((s) => s.id) : columns.filter((c) => visibilityOf(c) === "optional").map((c) => c.id);
13311
+ const initial = [...alwaysHidden, ...optionalHidden];
13312
+ const preserved = collectPreservedColumnIds(sorting, filters);
13313
+ return new Set(initial.filter((id) => !preserved.has(id)));
13314
+ }
13315
+ /** Collect IDs of columns that must remain visible (sorted, filtered). */
13316
+ function collectPreservedColumnIds(sorting, filters) {
13317
+ const sortedIds = (sorting ?? []).map((s) => s.column).filter((c) => c.type === "column").map((c) => c.id);
13318
+ const filterIds = !isNil$1(filters) ? collectFilterSpecColumns(filters).flatMap((c) => c.type === "column" ? [c.id] : []) : [];
13319
+ return /* @__PURE__ */ new Set([...sortedIds, ...filterIds]);
13320
+ }
13321
+ /** Remap column references in sorting entries through the resolver.
13322
+ * Unresolved entries are dropped with a warning (best-effort contract). */
13323
+ function remapSortingColumnIds(sorting, resolver) {
13324
+ return sorting?.flatMap((s) => {
13325
+ const col = resolver(s.column);
13326
+ if (isNil$1(col)) {
13327
+ console.warn(`Sorting column ${JSON.stringify(s.column)} does not match any discovered column — dropped.`);
13328
+ return [];
13329
+ }
13330
+ return [{
13331
+ ...s,
13332
+ column: col
13333
+ }];
13334
+ });
13335
+ }
13336
+ /** Remap column references in a filter tree through the resolver.
13337
+ * Unresolved leaves are dropped with a warning; empty groups are pruned. */
13338
+ function remapFilterColumnIds(filters, resolver) {
13339
+ if (isNil$1(filters)) return filters;
13340
+ const mapLeaf = (leaf) => {
13341
+ if (leaf.type === void 0) return leaf;
13342
+ const result = { ...leaf };
13343
+ if ("column" in result) {
13344
+ const c = resolver(result.column);
13345
+ if (isNil$1(c)) {
13346
+ console.warn(`Filter column ${JSON.stringify(result.column)} does not match any discovered column — dropped.`);
13347
+ return;
13348
+ }
13349
+ result.column = c;
13350
+ }
13351
+ if ("rhs" in result) {
13352
+ const c = resolver(result.rhs);
13353
+ if (isNil$1(c)) {
13354
+ console.warn(`Filter rhs ${JSON.stringify(result.rhs)} does not match any discovered column — dropped.`);
13355
+ return;
13356
+ }
13357
+ result.rhs = c;
13358
+ }
13359
+ return result;
13360
+ };
13361
+ const prune = (node) => {
13362
+ if (node.type === "and" || node.type === "or") {
13363
+ const kept = node.filters.map((f) => prune(f)).filter((f) => !isNil$1(f));
13364
+ if (kept.length === 0) return void 0;
13365
+ return {
13366
+ type: node.type,
13367
+ filters: kept
13368
+ };
13369
+ }
13370
+ if (node.type === "not") {
13371
+ const inner = prune(node.filter);
13372
+ return isNil$1(inner) ? void 0 : {
13373
+ type: "not",
13374
+ filter: inner
13375
+ };
13376
+ }
13377
+ return mapLeaf(node);
13378
+ };
13379
+ return prune(filters);
13380
+ }
13381
+ (/* @__PURE__ */ __commonJSMin(((exports, module) => {
13382
+ exports = module.exports = stringify;
13383
+ exports.getSerialize = serializer;
13384
+ function stringify(obj, replacer, spaces, cycleReplacer) {
13385
+ return JSON.stringify(obj, serializer(replacer, cycleReplacer), spaces);
13386
+ }
13387
+ function serializer(replacer, cycleReplacer) {
13388
+ var stack = [], keys = [];
13389
+ if (cycleReplacer == null) cycleReplacer = function(key, value) {
13390
+ if (stack[0] === value) return "[Circular ~]";
13391
+ return "[Circular ~." + keys.slice(0, stack.indexOf(value)).join(".") + "]";
13392
+ };
13393
+ return function(key, value) {
13394
+ if (stack.length > 0) {
13395
+ var thisPos = stack.indexOf(this);
13396
+ ~thisPos ? stack.splice(thisPos + 1) : stack.push(this);
13397
+ ~thisPos ? keys.splice(thisPos, Infinity, key) : keys.push(key);
13398
+ if (~stack.indexOf(value)) value = cycleReplacer.call(this, key, value);
13399
+ } else stack.push(value);
13400
+ return replacer == null ? value : replacer.call(this, key, value);
13401
+ };
13402
+ }
13403
+ })))();
13404
+ const PlErrorLike = objectType({
13405
+ type: literalType("PlError"),
13406
+ name: stringType(),
13407
+ message: stringType(),
13408
+ fullMessage: stringType().optional(),
13409
+ stack: stringType().optional()
13410
+ }).extend({
13411
+ cause: lazyType(() => ErrorLike).optional(),
13412
+ errors: lazyType(() => ErrorLike.array()).optional()
13413
+ });
13414
+ const ErrorLike = unionType([objectType({
13415
+ type: literalType("StandardError"),
13416
+ name: stringType(),
13417
+ message: stringType(),
13418
+ stack: stringType().optional()
13419
+ }).extend({
13420
+ cause: lazyType(() => ErrorLike).optional(),
13421
+ errors: lazyType(() => ErrorLike.array()).optional()
13422
+ }), PlErrorLike]);
13423
+ const ErrorShape = objectType({
13424
+ name: stringType(),
13425
+ message: stringType(),
13426
+ fullMessage: stringType().optional(),
13427
+ stack: stringType().optional()
13428
+ }).extend({
13429
+ cause: lazyType(() => ErrorShape).optional(),
13430
+ errors: lazyType(() => ErrorShape.array()).optional()
13431
+ });
13432
+ //#endregion
13433
+ //#region ../model/dist/render-utils.js
13434
+ /** A selector `name`/`domain` given as a bare string normalizes to a REGEX matcher, so an
13435
+ * exact name must be spelled out. `"pl7.app/frequency"` as a regex is unanchored and `.`
13436
+ * matches any character, which would also admit `pl7.app/frequencyRatio`. */
13437
+ const exactMatch = (value) => [{
13438
+ type: "exact",
13439
+ value
13440
+ }];
13441
+ /** Collapse discovery hits to one recipe per storage column, first hit wins.
13442
+ *
13443
+ * The retired `findColumns()` keyed its result map on the leaf column, merging several
13444
+ * reachability variants into one entry. `discover().getColumns()` returns one recipe PER
13445
+ * variant instead, and the value these options carry is the leaf id — so without this,
13446
+ * variants of one column become several dropdown entries sharing a single value. */
13447
+ function dedupByLeafId(recipes) {
13448
+ const seen = /* @__PURE__ */ new Set();
13449
+ return recipes.filter((recipe) => {
13450
+ const leaf = extractPObjectId(recipe.id);
13451
+ if (seen.has(leaf)) return false;
13452
+ seen.add(leaf);
13453
+ return true;
13454
+ });
13455
+ }
13456
+ /**
13457
+ * The p-columns of one workflow output, or undefined while the block is still computing.
13458
+ *
13459
+ * `getPColumns()` throws two different ways and they must not be treated alike. Mid-run the
13460
+ * resource tree is incomplete and traversal can throw — that is transient and means "not yet".
13461
+ * Once the block is ready-or-error, a throw means the workflow FAILED, and swallowing it makes a
13462
+ * crashed run indistinguishable from a healthy empty one: the output reports ok with no value,
13463
+ * the block shows Done, and the map is simply blank. That cost a day of debugging once already,
13464
+ * so past readiness the error is rethrown and surfaces on the output.
13465
+ */
13466
+ function outputPColumns(ctx, name) {
13467
+ try {
13468
+ const node = ctx.outputs?.resolve(name);
13469
+ if (node === void 0) return void 0;
13470
+ return node.getPColumns();
13471
+ } catch (e) {
13472
+ if (String(e).includes("field not found")) return void 0;
13473
+ if (ctx.outputs?.getIsReadyOrError() === false) return void 0;
13474
+ throw e;
13475
+ }
13476
+ }
13477
+ /**
13478
+ * Spec for a ref from the result pool, reported absent only once that absence has settled.
13479
+ *
13480
+ * `getPColumnSpecByRef` answers from the pool as it stands and registers nothing, so a column
13481
+ * that has not reached the pool yet is indistinguishable from one that never will. The output
13482
+ * settles at `undefined`, and a table fed by it then renders its not-ready text ("Select score
13483
+ * columns in Settings, then Run") for the seconds the pool takes to fill, although nothing is
13484
+ * wrong and the data is on its way. `getSpecs` does register — the middle layer marks the render
13485
+ * unstable while the pool is incomplete (`specs_from_pool_incomplete`) — so consulting it on a
13486
+ * miss keeps the output unsettled until the pool is complete and the absence is real.
13487
+ */
13488
+ function poolSpecByRef(ctx, ref) {
13489
+ const spec = ctx.resultPool.getPColumnSpecByRef(ref);
13490
+ if (spec !== void 0) return spec;
13491
+ ctx.resultPool.getSpecs();
13492
+ }
13493
+ //#endregion
13494
+ //#region ../model/dist/specs.js
13495
+ /**
13496
+ * Column and axis names this block shares with its workflow and with the profiler upstream.
13497
+ *
13498
+ * Every string here is a contract: change one and the matching literal in
13499
+ * `workflow/src/main.tpl.tengo` — or in the profiler that emits it — has to change with it, or
13500
+ * the column simply stops being found and an output goes quietly empty. They live in one file so
13501
+ * that obligation is visible rather than buried among the render helpers.
13502
+ */
13503
+ const STATE_MATRIX = "pl7.app/repertoire/stateMatrix";
13504
+ const LANDSCAPE_SCORE_REF = "pl7.app/repertoire/landscapeScoreRef";
13505
+ const MUTATION_ID_AXIS = "pl7.app/repertoire/mutationId";
13506
+ const MUTATION_VARIANT_LINK = "pl7.app/repertoire/mutationVariantLink";
13507
+ const BROWSABLE_MUTATION = "pl7.app/repertoire/browsableMutation";
13508
+ //#endregion
13509
+ //#region ../model/dist/drill-down-table.js
13510
+ /**
13511
+ * The Table tab: every variant carrying the active drill-down's substitution, at any mutation
13512
+ * count.
13513
+ *
13514
+ * The block exports only the `[variantKey, mutationId]` linker as the primary column; sequence,
13515
+ * mutations, mutation count, abundance and the scores are joined in from the result pool on the
13516
+ * shared variantKey axis, so none of them is copied into this block's own exports and the user
13517
+ * can surface any other variant-keyed column later.
13518
+ */
13519
+ function drillDownTableModel(ctx) {
13520
+ const mutationId = ctx.data.activeDrillDown;
13521
+ const linker = outputPColumns(ctx, "mutationVariantLinkPf")?.find((c) => c.spec.name === MUTATION_VARIANT_LINK);
13522
+ if (linker === void 0) return void 0;
13523
+ const mutationAxis = linker.spec.axesSpec.find((a) => a.name === MUTATION_ID_AXIS);
13524
+ if (mutationAxis === void 0) return void 0;
13525
+ const stateMatrixRef = ctx.data.stateMatrixRef;
13526
+ if (stateMatrixRef === void 0) return void 0;
13527
+ const stateSpec = poolSpecByRef(ctx, stateMatrixRef);
13528
+ if (!stateSpec) return void 0;
13529
+ const discovered = ColumnsCollection(["result_pool"]).discover({
13530
+ anchors: { main: stateSpec },
13531
+ mode: "enrichment",
13532
+ maxHops: 0,
13533
+ exclude: [{ annotations: { "pl7.app/isLinkerColumn": exactMatch("true") } }]
13534
+ }).getColumns();
13535
+ const secondary = dedupByLeafId(discovered).filter((recipe) => {
13536
+ const axes = recipe.getSpec().axesSpec;
13537
+ return axes.length === 1 && axes[0].name === "pl7.app/variantKey";
13538
+ });
13539
+ const scoreKey = ctx.data.drillDowns.find((d) => d.mutationId === mutationId)?.scoreKey;
13540
+ const activeScoreSpec = scoreKey === void 0 ? void 0 : discovered.find((recipe) => recipe.id === scoreKey)?.getSpec();
13541
+ const visibility = [
13542
+ {
13543
+ match: { name: exactMatch("pl7.app/label") },
13544
+ visibility: "default"
13545
+ },
13546
+ {
13547
+ match: { name: exactMatch("pl7.app/repertoire/mutations") },
13548
+ visibility: "default"
13549
+ },
13550
+ {
13551
+ match: { name: exactMatch("pl7.app/repertoire/mutationCount") },
13552
+ visibility: "default"
13553
+ },
13554
+ {
13555
+ match: {
13556
+ name: exactMatch("pl7.app/sequence"),
13557
+ annotations: { "pl7.app/isMainSequence": exactMatch("true") }
13558
+ },
13559
+ visibility: "default"
13560
+ }
13561
+ ];
13562
+ if (activeScoreSpec !== void 0) visibility.push({
13563
+ match: {
13564
+ name: exactMatch(activeScoreSpec.name),
13565
+ domain: Object.fromEntries(Object.entries(activeScoreSpec.domain ?? {}).map(([k, v]) => [k, exactMatch(v)]))
13566
+ },
13567
+ visibility: "default"
13568
+ });
13569
+ visibility.push({
13570
+ match: { name: ".*" },
13571
+ visibility: "optional"
13572
+ });
13573
+ return createPlDataTableV3(ctx, {
13574
+ primaryColumns: [DataColumn.fromColumn(linker)],
13575
+ columns: secondary,
13576
+ displayOptions: { visibility },
13577
+ filters: mutationId === void 0 ? void 0 : {
13578
+ type: "and",
13579
+ filters: [{
13580
+ type: "patternEquals",
13581
+ column: {
13582
+ type: "axis",
13583
+ id: {
13584
+ name: mutationAxis.name,
13585
+ type: mutationAxis.type,
13586
+ domain: mutationAxis.domain
13587
+ }
13588
+ },
13589
+ value: mutationId
13590
+ }]
13591
+ },
13592
+ tableState: ctx.data.drillDownTableState
13593
+ });
13594
+ }
13595
+ //#endregion
13596
+ //#region ../kind/dist/package.js
13597
+ var name = "@platforma-open/milaboratories.repertoire-mutation-heatmap.kind";
13598
+ var version = "1.0.0";
13599
+ //#endregion
13600
+ //#region ../node_modules/.pnpm/@platforma-sdk+block-kind@1.1.0/node_modules/@platforma-sdk/block-kind/dist/params.js
13601
+ /**
13602
+ * Establish that a value is an object whose fields a kind can read — the half of a params
13603
+ * check every kind needs and no two kinds differ on.
13604
+ *
13605
+ * Params that arrived from a template file are `unknown`, and before a single field can be
13606
+ * read the value has to be an object. Worth a shared function because the check is easy to
13607
+ * get wrong by hand: `typeof null` is `"object"`, `Object.keys(5)` is `[]` and
13608
+ * `Object.keys(["a"])` is `["0"]`, so a naive test lets `null`, a number and an array through
13609
+ * as if they were empty params.
13610
+ *
13611
+ * What each field must *be* is the kind's own business and stays in the kind, as plain
13612
+ * TypeScript: this package deliberately carries no validation library, so a kind author owes
13613
+ * it no schema.
13614
+ *
13615
+ * A key the kind does not declare is NOT refused. A parser returns the params to use, so a
13616
+ * field it never read is dropped and never reaches the block — the only question was whether
13617
+ * to also complain, and complaining costs more than it catches. It would mean each kind
13618
+ * restating its own field list as strings, with nothing checking that the list stayed in step
13619
+ * with the type: a field added to the contract and read by the parser, but missed in the list,
13620
+ * would turn into a kind that refuses files that are correct. What an unexpected key can
13621
+ * actually mean is a params contract from a different version of the kind, and that is
13622
+ * guarded where it belongs — by the version in the entry's `{name}@{selector}` reference.
13623
+ *
13624
+ * An assertion rather than a parser that returns a copy, so a kind reads its fields off the
13625
+ * value it was handed:
13626
+ *
13627
+ * ```ts
13628
+ * function parseInitializationParams(value: unknown): BlockParams {
13629
+ * assertParamsObject(value);
13630
+ *
13631
+ * const { numbers } = value;
13632
+ * if (numbers !== undefined && !isNumberArray(numbers)) {
13633
+ * throw new Error("'numbers' must be an array of numbers.");
13634
+ * }
13635
+ * return { numbers };
13636
+ * }
13637
+ * ```
13638
+ *
13639
+ * Messages are finished sentences addressed to whoever wrote the file, because that is who
13640
+ * reads them: a kind's rejection is reported against the entry that carried the params.
13641
+ *
13642
+ * @param value The params as they arrived
13643
+ * @throws if `value` is not an object
13644
+ */
13645
+ function assertParamsObject(value) {
13646
+ if (typeof value !== "object" || value === null || Array.isArray(value)) throw new Error(`Params must be an object, not ${describe(value)}.`);
13647
+ }
13648
+ /** What a value is, for a message that has to say why it is not an object. */
13649
+ function describe(value) {
13650
+ if (value === null) return "null";
13651
+ if (value === void 0) return "nothing";
13652
+ if (Array.isArray(value)) return "an array";
13653
+ return `a ${typeof value} (${JSON.stringify(value) ?? String(value)})`;
13654
+ }
13655
+ //#endregion
13656
+ //#region ../node_modules/.pnpm/@platforma-sdk+block-kind@1.1.0/node_modules/@platforma-sdk/block-kind/dist/index.js
13657
+ /**
13658
+ * Define a block kind.
13659
+ *
13660
+ * `meta` is the kind's identity — its own `{ name, version }`. Source it from
13661
+ * the package's `package.json` rather than hand-typing literals, so the on-wire
13662
+ * `{name}@{version}` cannot drift from what npm publishes and what the S3
13663
+ * manifest records (all read the same `package.json`):
13664
+ *
13665
+ * ```ts
13666
+ * // a kind package's src/index.ts
13667
+ * import { name, version } from "../package.json" with { type: "json" };
13668
+ * export const kind = defineBlockKind<Params>({ name, version });
13669
+ * ```
13670
+ *
13671
+ * rolldown inlines the JSON import (tree-shaken to the two strings) into the
13672
+ * bundled `kind.js`, so no build-time injection is needed.
13673
+ *
13674
+ * A kind must also declare `parseInitializationParams` — the runtime check applied to params
13675
+ * that came from a template file rather than from typed code. See
13676
+ * {@link CompiledBlockKind} for what it must do.
13677
+ *
13678
+ * @typeParam BlockParams - shape of the params a block of this kind reads. Pinned both
13679
+ * as a type and by `parseInitializationParams`, whose return type is checked against it.
13680
+ */
13681
+ function defineBlockKind(meta) {
13682
+ return Object.freeze({
13683
+ kindSchema: "v1",
13684
+ name: meta.name,
13685
+ version: meta.version,
13686
+ parseInitializationParams: meta.parseInitializationParams
13687
+ });
13688
+ }
13689
+ //#endregion
13690
+ //#region ../kind/dist/index.js
13691
+ /**
13692
+ * The same contract at runtime, for params that arrive from a template file
13693
+ * rather than from typed code.
13694
+ *
13695
+ * The contract names no fields, so there is nothing to read and nothing to
13696
+ * validate beyond the value being an object at all. Keys a template supplies
13697
+ * anyway are dropped by not being read. The return type holds this in step: the
13698
+ * moment `BlockParams` declares a required field, `return {}` stops compiling.
13699
+ */
13700
+ function parseInitializationParams(value) {
13701
+ assertParamsObject(value);
13702
+ return {};
13703
+ }
13704
+ const kind = defineBlockKind({
13705
+ name,
13706
+ version,
13707
+ parseInitializationParams
13708
+ });
13709
+ //#endregion
13710
+ //#region ../model/dist/index.js
13711
+ /**
13712
+ * The section href of one drill-down. The model builds the section list with it and the UI
13713
+ * navigates with it, so the two cannot drift apart on the encoding — which they would, silently,
13714
+ * the first time a designator needed escaping.
13715
+ */
13716
+ /**
13717
+ * `A5C · Bin score (5.5)` — the substitution and the score it is measured on.
13718
+ *
13719
+ * Derived from the produced columns rather than stored on the drill-down: a stored label goes
13720
+ * stale when a score is renamed upstream, and would be missing entirely on any drill-down opened
13721
+ * before it was introduced. Falls back to the bare designator before a run has produced columns.
13722
+ */
13723
+ function drillDownLabel(mutationId, scoreLabel) {
13724
+ return scoreLabel ? `${mutationId} · ${scoreLabel}` : mutationId;
13725
+ }
13726
+ /**
13727
+ * The landscape charts the last run produced, in the user's score order.
13728
+ *
13729
+ * Shared by the `landscapePanels` output and by `.sections()`, which needs the same list to name
13730
+ * one page per score — two derivations of "which charts exist" would drift the moment one of
13731
+ * them changed.
13732
+ */
13733
+ function landscapePanelsFrom(pCols) {
13734
+ if (pCols === void 0) return void 0;
13735
+ const panels = [];
13736
+ for (const col of pCols) {
13737
+ if (col.spec.name !== "pl7.app/repertoire/singleMutantValue") continue;
13738
+ const key = col.spec.annotations?.[LANDSCAPE_SCORE_REF];
13739
+ if (key === void 0) continue;
13740
+ panels.push({
13741
+ key,
13742
+ label: col.spec.annotations?.["pl7.app/label"] ?? "Score",
13743
+ index: Number(col.spec.annotations?.["pl7.app/repertoire/landscapeScoreIndex"] ?? "0"),
13744
+ spec: col.spec
13745
+ });
13746
+ }
13747
+ panels.sort((a, b) => a.index - b.index);
13748
+ return panels;
13749
+ }
13750
+ /** The section href of one landscape page. */
13751
+ function landscapeHref(scoreKey) {
13752
+ return `/?score=${encodeURIComponent(scoreKey)}`;
13753
+ }
13754
+ /** `Landscape · Bin score (5.5)` — what the sidebar shows for one landscape page. */
13755
+ function landscapeLabel(scoreLabel) {
13756
+ return `Landscape · ${scoreLabel}`;
13757
+ }
13758
+ /** score id -> display label, from the columns the last run produced. */
13759
+ function scoreLabelsByKey(pCols) {
13760
+ const labels = {};
13761
+ for (const col of pCols ?? []) {
13762
+ if (col.spec.name !== "pl7.app/repertoire/singleMutantValue") continue;
13763
+ const key = col.spec.annotations?.[LANDSCAPE_SCORE_REF];
13764
+ const label = col.spec.annotations?.["pl7.app/label"];
13765
+ if (key !== void 0 && label !== void 0) labels[key] = label;
13766
+ }
13767
+ return labels;
13768
+ }
13769
+ function drillDownHref(mutationId) {
13770
+ return `/drilldown?m=${encodeURIComponent(mutationId)}`;
13771
+ }
13772
+ const NO_DATASET_LABEL = "No dataset selected";
11460
13773
  const dataModel = new DataModelBuilder({ kind }).from("v1").migrate("v2", (v1) => ({
11461
13774
  ...v1,
11462
13775
  singleMutantHeatmapStates: {}
13776
+ })).migrate("v3", (v2) => ({
13777
+ ...v2,
13778
+ singleMutantHeatmapState: withEmptyNAValue(v2.singleMutantHeatmapState),
13779
+ singleMutantHeatmapStates: Object.fromEntries(Object.entries(v2.singleMutantHeatmapStates).map(([key, state]) => [key, withEmptyNAValue(state)]))
13780
+ })).migrate("v4", (v3) => ({
13781
+ ...v3,
13782
+ ...mapChartStates(v3, withParentOnXAxis)
13783
+ })).migrate("v5", (v4) => ({
13784
+ ...v4,
13785
+ drillDowns: [],
13786
+ drillDownChartState: makeDrillDownChartState(),
13787
+ drillDownTableState: createPlDataTableStateV2(),
13788
+ ...mapChartStates(v4, withRegionColoursReseeded)
11463
13789
  })).init(() => ({
13790
+ drillDowns: [],
13791
+ drillDownChartState: makeDrillDownChartState(),
13792
+ drillDownTableState: createPlDataTableStateV2(),
11464
13793
  roundFrequencyRefs: [],
11465
13794
  compositionEpsilon: 1e-6,
11466
13795
  scoreRefs: [],
@@ -11476,7 +13805,10 @@ const dataModel = new DataModelBuilder({ kind }).from("v1").migrate("v2", (v1) =
11476
13805
  } },
11477
13806
  axesSettings: {
11478
13807
  other: { facetColumns: 1 },
11479
- axisX: { cellSize: 20 },
13808
+ axisX: {
13809
+ cellSize: 20,
13810
+ axisLabelsAngle: 45
13811
+ },
11480
13812
  axisY: {
11481
13813
  hideAxisLabels: false,
11482
13814
  cellSize: 20
@@ -11513,7 +13845,7 @@ const platforma$1 = BlockModelV3.create({
11513
13845
  }).output("scoreOptions", (ctx) => {
11514
13846
  const stateMatrixRef = ctx.data.stateMatrixRef;
11515
13847
  if (stateMatrixRef === void 0) return void 0;
11516
- const stateSpec = ctx.resultPool.getPColumnSpecByRef(stateMatrixRef);
13848
+ const stateSpec = poolSpecByRef(ctx, stateMatrixRef);
11517
13849
  if (!stateSpec) return void 0;
11518
13850
  const anchors = { main: stateSpec };
11519
13851
  const columns = ColumnsCollection(["result_pool"]).discover({
@@ -11545,7 +13877,7 @@ const platforma$1 = BlockModelV3.create({
11545
13877
  }).output("roundFrequencyOptions", (ctx) => {
11546
13878
  const stateMatrixRef = ctx.data.stateMatrixRef;
11547
13879
  if (stateMatrixRef === void 0) return void 0;
11548
- const stateSpec = ctx.resultPool.getPColumnSpecByRef(stateMatrixRef);
13880
+ const stateSpec = poolSpecByRef(ctx, stateMatrixRef);
11549
13881
  if (!stateSpec) return void 0;
11550
13882
  return dedupByLeafId(ColumnsCollection(["result_pool"]).discover({
11551
13883
  include: { name: exactMatch("pl7.app/frequency") },
@@ -11569,66 +13901,61 @@ const platforma$1 = BlockModelV3.create({
11569
13901
  if (stateMatrixRef === void 0) return void 0;
11570
13902
  return ctx.resultPool.getPColumnByRef(stateMatrixRef)?.id;
11571
13903
  }).outputWithStatus("singleMutantHeatmapPf", (ctx) => {
11572
- try {
11573
- const pCols = ctx.outputs?.resolve("singleMutantHeatmapPf")?.getPColumns();
11574
- if (pCols === void 0) return void 0;
11575
- return createPFrameForGraphs(ctx, pCols);
11576
- } catch {
11577
- return;
11578
- }
13904
+ const pCols = outputPColumns(ctx, "singleMutantHeatmapPf");
13905
+ if (pCols === void 0) return void 0;
13906
+ return createPFrameForGraphs(ctx, pCols);
11579
13907
  }).output("singleMutantHeatmapPCols", (ctx) => {
11580
- try {
11581
- return ctx.outputs?.resolve("singleMutantHeatmapPf")?.getPColumns();
11582
- } catch {
11583
- return;
11584
- }
11585
- }).output("landscapePanels", (ctx) => {
11586
- let pCols;
11587
- try {
11588
- pCols = ctx.outputs?.resolve("singleMutantHeatmapPf")?.getPColumns();
11589
- } catch {
11590
- return;
11591
- }
13908
+ return outputPColumns(ctx, "singleMutantHeatmapPf");
13909
+ }).output("landscapePanels", (ctx) => landscapePanelsFrom(outputPColumns(ctx, "singleMutantHeatmapPf"))).outputWithStatus("drillDownHeatmapPf", (ctx) => {
13910
+ const pCols = outputPColumns(ctx, "drillDownHeatmapPf");
11592
13911
  if (pCols === void 0) return void 0;
11593
- const panels = [];
11594
- for (const col of pCols) {
11595
- if (col.spec.name !== LANDSCAPE_VALUE) continue;
11596
- const key = col.spec.annotations?.[LANDSCAPE_SCORE_REF];
11597
- if (key === void 0) continue;
11598
- panels.push({
11599
- key,
11600
- label: col.spec.annotations?.["pl7.app/label"] ?? "Score",
11601
- index: Number(col.spec.annotations?.[LANDSCAPE_SCORE_INDEX] ?? "0"),
11602
- spec: col.spec
11603
- });
11604
- }
11605
- panels.sort((a, b) => a.index - b.index);
11606
- return panels;
11607
- }).outputWithStatus("compositionHeatmapPf", (ctx) => {
11608
- try {
11609
- const pCols = ctx.outputs?.resolve("compositionHeatmapPf")?.getPColumns();
11610
- if (pCols === void 0) return void 0;
11611
- return createPFrameForGraphs(ctx, pCols);
11612
- } catch {
11613
- return;
11614
- }
13912
+ return createPFrameForGraphs(ctx, pCols);
13913
+ }).output("drillDownHeatmapPCols", (ctx) => {
13914
+ return outputPColumns(ctx, "drillDownHeatmapPf");
13915
+ }).output("browsableMutationsPf", (ctx) => {
13916
+ const pCols = outputPColumns(ctx, "browsableMutationsPf");
13917
+ if (pCols === void 0 || pCols.length === 0) return void 0;
13918
+ return ctx.createPFrame(pCols);
13919
+ }).output("browsableMutationsColId", (ctx) => {
13920
+ return outputPColumns(ctx, "browsableMutationsPf")?.find((c) => c.spec.name === BROWSABLE_MUTATION)?.id;
13921
+ }).outputWithStatus("drillDownTable", (ctx) => drillDownTableModel(ctx)).outputWithStatus("compositionHeatmapPf", (ctx) => {
13922
+ const pCols = outputPColumns(ctx, "compositionHeatmapPf");
13923
+ if (pCols === void 0) return void 0;
13924
+ return createPFrameForGraphs(ctx, pCols);
11615
13925
  }).output("compositionHeatmapPCols", (ctx) => {
11616
- try {
11617
- return ctx.outputs?.resolve("compositionHeatmapPf")?.getPColumns();
11618
- } catch {
11619
- return;
11620
- }
13926
+ return outputPColumns(ctx, "compositionHeatmapPf");
11621
13927
  }).output("isRunning", (ctx) => ctx.outputs?.getIsReadyOrError() === false).title(() => "Mutation Explorer").subtitle((ctx) => ctx.data.customBlockLabel || ctx.data.defaultBlockLabel || NO_DATASET_LABEL).sections((ctx) => {
11622
- const sections = [{
13928
+ const pCols = outputPColumns(ctx, "singleMutantHeatmapPf");
13929
+ const panels = landscapePanelsFrom(pCols) ?? [];
13930
+ const sections = [];
13931
+ if (panels.length === 0) sections.push({
11623
13932
  type: "link",
11624
13933
  href: "/",
11625
13934
  label: "Single Mutation Landscape"
11626
- }];
11627
- if (ctx.data.roundFrequencyRefs.length >= 2) sections.push({
13935
+ });
13936
+ else for (const p of panels) sections.push({
11628
13937
  type: "link",
11629
- href: "/composition",
11630
- label: "Enrichment Analysis"
13938
+ href: landscapeHref(p.key),
13939
+ label: landscapeLabel(p.label)
11631
13940
  });
13941
+ const drillDowns = ctx.data.drillDowns ?? [];
13942
+ if (drillDowns.length > 0) {
13943
+ const scoreLabels = scoreLabelsByKey(pCols);
13944
+ sections.push({ type: "delimiter" });
13945
+ for (const d of drillDowns) sections.push({
13946
+ type: "link",
13947
+ href: drillDownHref(d.mutationId),
13948
+ label: drillDownLabel(d.mutationId, scoreLabels[d.scoreKey])
13949
+ });
13950
+ }
13951
+ if (ctx.data.roundFrequencyRefs.length >= 2) {
13952
+ sections.push({ type: "delimiter" });
13953
+ sections.push({
13954
+ type: "link",
13955
+ href: "/composition",
13956
+ label: "Enrichment Analysis"
13957
+ });
13958
+ }
11632
13959
  return sections;
11633
13960
  }).done();
11634
13961
  //#endregion