@platforma-sdk/model 1.63.1 → 1.63.12
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/_virtual/_rolldown/runtime.cjs +12 -22
- package/dist/_virtual/_rolldown/runtime.js +6 -11
- package/dist/annotations/converter.cjs +4 -5
- package/dist/annotations/converter.cjs.map +1 -1
- package/dist/annotations/converter.d.ts.map +1 -0
- package/dist/annotations/converter.js +1 -2
- package/dist/annotations/converter.js.map +1 -1
- package/dist/annotations/index.cjs +1 -1
- package/dist/annotations/index.js +1 -1
- package/dist/annotations/types.d.ts +0 -1
- package/dist/annotations/types.d.ts.map +1 -0
- package/dist/bconfig/index.cjs +2 -2
- package/dist/bconfig/index.js +2 -2
- package/dist/bconfig/lambdas.d.ts +0 -1
- package/dist/bconfig/lambdas.d.ts.map +1 -0
- package/dist/bconfig/normalization.cjs +4 -5
- package/dist/bconfig/normalization.cjs.map +1 -1
- package/dist/bconfig/normalization.d.ts.map +1 -0
- package/dist/bconfig/normalization.js +1 -2
- package/dist/bconfig/normalization.js.map +1 -1
- package/dist/bconfig/types.cjs +1 -2
- package/dist/bconfig/types.cjs.map +1 -1
- package/dist/bconfig/types.d.ts +0 -1
- package/dist/bconfig/types.d.ts.map +1 -0
- package/dist/bconfig/types.js +1 -1
- package/dist/bconfig/util.d.ts.map +1 -0
- package/dist/bconfig/v3.d.ts.map +1 -0
- package/dist/block_api_v1.d.ts.map +1 -0
- package/dist/block_api_v2.d.ts.map +1 -0
- package/dist/block_api_v3.d.ts.map +1 -0
- package/dist/block_migrations.cjs +2 -3
- package/dist/block_migrations.cjs.map +1 -1
- package/dist/block_migrations.d.ts.map +1 -0
- package/dist/block_migrations.js +1 -2
- package/dist/block_migrations.js.map +1 -1
- package/dist/block_model.cjs +16 -17
- package/dist/block_model.cjs.map +1 -1
- package/dist/block_model.d.ts +0 -2
- package/dist/block_model.d.ts.map +1 -0
- package/dist/block_model.js +4 -5
- package/dist/block_model.js.map +1 -1
- package/dist/block_model_legacy.cjs +10 -11
- package/dist/block_model_legacy.cjs.map +1 -1
- package/dist/block_model_legacy.d.ts +0 -3
- package/dist/block_model_legacy.d.ts.map +1 -0
- package/dist/block_model_legacy.js +1 -2
- package/dist/block_model_legacy.js.map +1 -1
- package/dist/block_state_patch.d.ts.map +1 -0
- package/dist/block_state_util.cjs +1 -2
- package/dist/block_state_util.cjs.map +1 -1
- package/dist/block_state_util.d.ts.map +1 -0
- package/dist/block_state_util.js +1 -1
- package/dist/block_state_util.js.map +1 -1
- package/dist/block_storage.cjs +5 -12
- package/dist/block_storage.cjs.map +1 -1
- package/dist/block_storage.d.ts.map +1 -0
- package/dist/block_storage.js +5 -11
- package/dist/block_storage.js.map +1 -1
- package/dist/block_storage_callbacks.cjs +4 -5
- package/dist/block_storage_callbacks.cjs.map +1 -1
- package/dist/block_storage_callbacks.js +3 -4
- package/dist/block_storage_callbacks.js.map +1 -1
- package/dist/block_storage_facade.cjs +2 -3
- package/dist/block_storage_facade.cjs.map +1 -1
- package/dist/block_storage_facade.d.ts +0 -1
- package/dist/block_storage_facade.d.ts.map +1 -0
- package/dist/block_storage_facade.js +1 -2
- package/dist/block_storage_facade.js.map +1 -1
- package/dist/columns/column_collection_builder.cjs +6 -7
- package/dist/columns/column_collection_builder.cjs.map +1 -1
- package/dist/columns/column_collection_builder.d.ts.map +1 -0
- package/dist/columns/column_collection_builder.js +1 -2
- package/dist/columns/column_collection_builder.js.map +1 -1
- package/dist/columns/column_selector.cjs +1 -2
- package/dist/columns/column_selector.cjs.map +1 -1
- package/dist/columns/column_selector.d.ts.map +1 -0
- package/dist/columns/column_selector.js +1 -1
- package/dist/columns/column_selector.js.map +1 -1
- package/dist/columns/column_snapshot.cjs +1 -2
- package/dist/columns/column_snapshot.cjs.map +1 -1
- package/dist/columns/column_snapshot.d.ts.map +1 -0
- package/dist/columns/column_snapshot.js +1 -1
- package/dist/columns/column_snapshot_provider.cjs +1 -2
- package/dist/columns/column_snapshot_provider.cjs.map +1 -1
- package/dist/columns/column_snapshot_provider.d.ts.map +1 -0
- package/dist/columns/column_snapshot_provider.js +1 -1
- package/dist/columns/column_snapshot_provider.js.map +1 -1
- package/dist/columns/ctx_column_sources.cjs +3 -4
- package/dist/columns/ctx_column_sources.cjs.map +1 -1
- package/dist/columns/ctx_column_sources.d.ts +0 -1
- package/dist/columns/ctx_column_sources.d.ts.map +1 -0
- package/dist/columns/ctx_column_sources.js +1 -2
- package/dist/columns/ctx_column_sources.js.map +1 -1
- package/dist/columns/index.cjs +5 -5
- package/dist/columns/index.js +5 -5
- package/dist/components/PFrameForGraphs.cjs +4 -5
- package/dist/components/PFrameForGraphs.cjs.map +1 -1
- package/dist/components/PFrameForGraphs.d.ts +0 -1
- package/dist/components/PFrameForGraphs.d.ts.map +1 -0
- package/dist/components/PFrameForGraphs.js +2 -3
- package/dist/components/PFrameForGraphs.js.map +1 -1
- package/dist/components/PlAnnotations/filter.d.ts.map +1 -0
- package/dist/components/PlAnnotations/filters_ui.cjs +1 -2
- package/dist/components/PlAnnotations/filters_ui.cjs.map +1 -1
- package/dist/components/PlAnnotations/filters_ui.d.ts +0 -2
- package/dist/components/PlAnnotations/filters_ui.d.ts.map +1 -0
- package/dist/components/PlAnnotations/filters_ui.js +1 -1
- package/dist/components/PlAnnotations/filters_ui.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +9 -10
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts +0 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +1 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +14 -15
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +0 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +1 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.cjs +3 -4
- package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts +0 -1
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/index.js +1 -2
- package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTableSheet.cjs +1 -2
- package/dist/components/PlDataTable/createPlDataTableSheet.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTableSheet.d.ts +0 -1
- package/dist/components/PlDataTable/createPlDataTableSheet.d.ts.map +1 -0
- package/dist/components/PlDataTable/createPlDataTableSheet.js +1 -1
- package/dist/components/PlDataTable/index.cjs +5 -5
- package/dist/components/PlDataTable/index.js +5 -5
- package/dist/components/PlDataTable/labels.cjs +4 -5
- package/dist/components/PlDataTable/labels.cjs.map +1 -1
- package/dist/components/PlDataTable/labels.js +1 -2
- package/dist/components/PlDataTable/labels.js.map +1 -1
- package/dist/components/PlDataTable/state-migration.cjs +4 -5
- package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
- package/dist/components/PlDataTable/state-migration.d.ts.map +1 -0
- package/dist/components/PlDataTable/state-migration.js +1 -2
- package/dist/components/PlDataTable/state-migration.js.map +1 -1
- package/dist/components/PlDataTable/typesV4.d.ts.map +1 -0
- package/dist/components/PlDataTable/typesV5.d.ts +0 -1
- package/dist/components/PlDataTable/typesV5.d.ts.map +1 -0
- package/dist/components/PlMultiSequenceAlignment.cjs +2 -3
- package/dist/components/PlMultiSequenceAlignment.cjs.map +1 -1
- package/dist/components/PlMultiSequenceAlignment.d.ts.map +1 -0
- package/dist/components/PlMultiSequenceAlignment.js +1 -2
- package/dist/components/PlMultiSequenceAlignment.js.map +1 -1
- package/dist/components/PlSelectionModel.cjs +1 -2
- package/dist/components/PlSelectionModel.cjs.map +1 -1
- package/dist/components/PlSelectionModel.d.ts.map +1 -0
- package/dist/components/PlSelectionModel.js +1 -1
- package/dist/components/index.cjs +11 -11
- package/dist/components/index.d.ts +0 -2
- package/dist/components/index.js +10 -10
- package/dist/config/actions.cjs +1 -2
- package/dist/config/actions.cjs.map +1 -1
- package/dist/config/actions.d.ts.map +1 -0
- package/dist/config/actions.js +1 -1
- package/dist/config/actions_kinds.d.ts.map +1 -0
- package/dist/config/index.cjs +1 -1
- package/dist/config/index.js +1 -1
- package/dist/config/model.d.ts.map +1 -0
- package/dist/config/model_meta.d.ts.map +1 -0
- package/dist/config/type_engine.d.ts.map +1 -0
- package/dist/config/type_util.d.ts.map +1 -0
- package/dist/env_value.cjs +1 -2
- package/dist/env_value.cjs.map +1 -1
- package/dist/env_value.d.ts.map +1 -0
- package/dist/env_value.js +1 -1
- package/dist/env_value.js.map +1 -1
- package/dist/filters/converters/filterToQuery.cjs +3 -4
- package/dist/filters/converters/filterToQuery.cjs.map +1 -1
- package/dist/filters/converters/filterToQuery.d.ts.map +1 -0
- package/dist/filters/converters/filterToQuery.js +1 -2
- package/dist/filters/converters/filterToQuery.js.map +1 -1
- package/dist/filters/converters/filterUiToExpressionImpl.cjs +3 -4
- package/dist/filters/converters/filterUiToExpressionImpl.cjs.map +1 -1
- package/dist/filters/converters/filterUiToExpressionImpl.d.ts.map +1 -0
- package/dist/filters/converters/filterUiToExpressionImpl.js +1 -2
- package/dist/filters/converters/filterUiToExpressionImpl.js.map +1 -1
- package/dist/filters/converters/index.cjs +2 -2
- package/dist/filters/converters/index.js +2 -2
- package/dist/filters/distill.cjs +3 -4
- package/dist/filters/distill.cjs.map +1 -1
- package/dist/filters/distill.d.ts.map +1 -0
- package/dist/filters/distill.js +1 -2
- package/dist/filters/distill.js.map +1 -1
- package/dist/filters/index.cjs +4 -4
- package/dist/filters/index.d.ts +0 -1
- package/dist/filters/index.js +3 -3
- package/dist/filters/traverse.cjs +1 -2
- package/dist/filters/traverse.cjs.map +1 -1
- package/dist/filters/traverse.js +1 -1
- package/dist/filters/traverse.js.map +1 -1
- package/dist/filters/types.d.ts.map +1 -0
- package/dist/index.cjs +78 -76
- package/dist/index.d.ts +0 -9
- package/dist/index.js +3 -6
- package/dist/internal.cjs +1 -2
- package/dist/internal.cjs.map +1 -1
- package/dist/internal.js +1 -1
- package/dist/internal.js.map +1 -1
- package/dist/labels/derive_distinct_labels.cjs +2 -3
- package/dist/labels/derive_distinct_labels.cjs.map +1 -1
- package/dist/labels/derive_distinct_labels.d.ts.map +1 -0
- package/dist/labels/derive_distinct_labels.js +1 -2
- package/dist/labels/derive_distinct_labels.js.map +1 -1
- package/dist/labels/index.cjs +2 -2
- package/dist/labels/index.js +2 -2
- package/dist/labels/write_labels_to_specs.cjs +2 -3
- package/dist/labels/write_labels_to_specs.cjs.map +1 -1
- package/dist/labels/write_labels_to_specs.d.ts +0 -2
- package/dist/labels/write_labels_to_specs.d.ts.map +1 -0
- package/dist/labels/write_labels_to_specs.js +1 -2
- package/dist/labels/write_labels_to_specs.js.map +1 -1
- package/dist/package.cjs +7 -8
- package/dist/package.js +2 -2
- package/dist/pframe.cjs +2 -3
- package/dist/pframe.cjs.map +1 -1
- package/dist/pframe.d.ts.map +1 -0
- package/dist/pframe.js +1 -2
- package/dist/pframe.js.map +1 -1
- package/dist/pframe_utils/axes.cjs +2 -3
- package/dist/pframe_utils/axes.cjs.map +1 -1
- package/dist/pframe_utils/axes.d.ts +0 -1
- package/dist/pframe_utils/axes.d.ts.map +1 -0
- package/dist/pframe_utils/axes.js +1 -2
- package/dist/pframe_utils/axes.js.map +1 -1
- package/dist/pframe_utils/columns.cjs +5 -6
- package/dist/pframe_utils/columns.cjs.map +1 -1
- package/dist/pframe_utils/columns.d.ts +0 -1
- package/dist/pframe_utils/columns.d.ts.map +1 -0
- package/dist/pframe_utils/columns.js +1 -2
- package/dist/pframe_utils/columns.js.map +1 -1
- package/dist/pframe_utils/index.cjs +3 -4
- package/dist/pframe_utils/index.cjs.map +1 -1
- package/dist/pframe_utils/index.d.ts.map +1 -0
- package/dist/pframe_utils/index.js +2 -3
- package/dist/pframe_utils/index.js.map +1 -1
- package/dist/platforma.d.ts.map +1 -0
- package/dist/plugin_handle.cjs +1 -2
- package/dist/plugin_handle.cjs.map +1 -1
- package/dist/plugin_handle.d.ts.map +1 -0
- package/dist/plugin_handle.js +1 -1
- package/dist/plugin_model.cjs +3 -4
- package/dist/plugin_model.cjs.map +1 -1
- package/dist/plugin_model.d.ts +0 -1
- package/dist/plugin_model.d.ts.map +1 -0
- package/dist/plugin_model.js +1 -2
- package/dist/plugin_model.js.map +1 -1
- package/dist/raw_globals.cjs +3 -4
- package/dist/raw_globals.cjs.map +1 -1
- package/dist/raw_globals.d.ts.map +1 -0
- package/dist/raw_globals.js +1 -2
- package/dist/raw_globals.js.map +1 -1
- package/dist/ref_util.cjs +3 -4
- package/dist/ref_util.cjs.map +1 -1
- package/dist/ref_util.d.ts +0 -2
- package/dist/ref_util.d.ts.map +1 -0
- package/dist/ref_util.js +1 -2
- package/dist/ref_util.js.map +1 -1
- package/dist/render/accessor.cjs +4 -5
- package/dist/render/accessor.cjs.map +1 -1
- package/dist/render/accessor.d.ts.map +1 -0
- package/dist/render/accessor.js +1 -2
- package/dist/render/accessor.js.map +1 -1
- package/dist/render/api.cjs +10 -11
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +0 -1
- package/dist/render/api.d.ts.map +1 -0
- package/dist/render/api.js +1 -2
- package/dist/render/api.js.map +1 -1
- package/dist/render/future.cjs +2 -3
- package/dist/render/future.cjs.map +1 -1
- package/dist/render/future.d.ts.map +1 -0
- package/dist/render/future.js +1 -2
- package/dist/render/future.js.map +1 -1
- package/dist/render/index.cjs +8 -8
- package/dist/render/index.d.ts +1 -2
- package/dist/render/index.js +7 -7
- package/dist/render/internal.cjs +7 -9
- package/dist/render/internal.cjs.map +1 -1
- package/dist/render/internal.d.ts.map +1 -0
- package/dist/render/internal.js +1 -2
- package/dist/render/internal.js.map +1 -1
- package/dist/render/traversal_ops.d.ts.map +1 -0
- package/dist/render/util/axis_filtering.cjs +1 -2
- package/dist/render/util/axis_filtering.cjs.map +1 -1
- package/dist/render/util/axis_filtering.d.ts.map +1 -0
- package/dist/render/util/axis_filtering.js +1 -1
- package/dist/render/util/column_collection.cjs +5 -6
- package/dist/render/util/column_collection.cjs.map +1 -1
- package/dist/render/util/column_collection.d.ts +0 -1
- package/dist/render/util/column_collection.d.ts.map +1 -0
- package/dist/render/util/column_collection.js +1 -2
- package/dist/render/util/column_collection.js.map +1 -1
- package/dist/render/util/index.cjs +4 -4
- package/dist/render/util/index.js +4 -4
- package/dist/render/util/label.cjs +2 -3
- package/dist/render/util/label.cjs.map +1 -1
- package/dist/render/util/label.d.ts.map +1 -0
- package/dist/render/util/label.js +1 -2
- package/dist/render/util/label.js.map +1 -1
- package/dist/render/util/pcolumn_data.cjs +9 -10
- package/dist/render/util/pcolumn_data.cjs.map +1 -1
- package/dist/render/util/pcolumn_data.d.ts.map +1 -0
- package/dist/render/util/pcolumn_data.js +7 -8
- package/dist/render/util/pcolumn_data.js.map +1 -1
- package/dist/render/util/pframe_upgraders.cjs +1 -2
- package/dist/render/util/pframe_upgraders.cjs.map +1 -1
- package/dist/render/util/pframe_upgraders.js +1 -1
- package/dist/render/util/split_selectors.d.ts.map +1 -0
- package/dist/services/block_services.cjs +2 -3
- package/dist/services/block_services.cjs.map +1 -1
- package/dist/services/block_services.d.ts +2 -2
- package/dist/services/block_services.d.ts.map +1 -0
- package/dist/services/block_services.js +1 -2
- package/dist/services/block_services.js.map +1 -1
- package/dist/services/index.cjs +2 -2
- package/dist/services/index.js +2 -2
- package/dist/services/service_bridge.cjs +1 -2
- package/dist/services/service_bridge.cjs.map +1 -1
- package/dist/services/service_bridge.d.ts.map +1 -0
- package/dist/services/service_bridge.js +1 -1
- package/dist/services/service_resolve.d.ts.map +1 -0
- package/dist/version.cjs +2 -4
- package/dist/version.cjs.map +1 -1
- package/dist/version.d.ts.map +1 -0
- package/dist/version.js +1 -2
- package/dist/version.js.map +1 -1
- package/package.json +12 -12
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
2
|
let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
|
|
3
3
|
let _milaboratories_helpers = require("@milaboratories/helpers");
|
|
4
|
-
|
|
5
4
|
//#region src/labels/derive_distinct_labels.ts
|
|
6
5
|
const DISTANCE_PENALTY = .001;
|
|
7
6
|
const LABEL_TYPE = "__LABEL__";
|
|
@@ -150,7 +149,7 @@ function minimizeTypeSet(typeSet, records, stats, forceTraceElements, options, s
|
|
|
150
149
|
}
|
|
151
150
|
return result;
|
|
152
151
|
}
|
|
153
|
-
|
|
154
152
|
//#endregion
|
|
155
153
|
exports.deriveDistinctLabels = deriveDistinctLabels;
|
|
154
|
+
|
|
156
155
|
//# sourceMappingURL=derive_distinct_labels.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive_distinct_labels.cjs","names":["Annotation"],"sources":["../../src/labels/derive_distinct_labels.ts"],"sourcesContent":["import {\n Annotation,\n parseJson,\n readAnnotation,\n type CanonicalizedJson,\n type PObjectSpec,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\n\nexport type WithLabel<T> = {\n value: T;\n label: string;\n};\n\ntype TraceEntry = {\n id?: string;\n type: string;\n label: string;\n importance?: number;\n};\n\nexport type Trace = TraceEntry[];\n\nexport type Entry =\n | PObjectSpec\n | { spec: PObjectSpec; prefixTrace?: TraceEntry[]; suffixTrace?: TraceEntry[] };\n\nexport type DeriveLabelsOptions = {\n /** Separator to use between label parts (\" / \" by default) */\n separator?: string;\n /** If true, label will be added as suffix (at the end of the generated label). By default label added as a prefix. */\n addLabelAsSuffix?: boolean;\n /** Force inclusion of native column label */\n includeNativeLabel?: boolean;\n /** Trace elements list that will be forced to be included in the label. */\n forceTraceElements?: string[];\n};\n\nexport function deriveDistinctLabels<T extends Entry>(\n values: T[],\n options: DeriveLabelsOptions = {},\n): WithLabel<T>[] {\n const forceTraceElements =\n options.forceTraceElements !== undefined && options.forceTraceElements.length > 0\n ? new Set(options.forceTraceElements)\n : undefined;\n const separator = options.separator ?? \" / \";\n\n // Phase 1: enrich each value with parsed trace\n const records = values.map((v) => enrichRecord(v, options));\n\n // Phase 2: collect global type statistics\n const stats = collectTypeStats(records);\n\n // Phase 3: classify types into main (present everywhere) and secondary\n const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);\n\n const build = (typeSet: Set<string>, force: boolean) =>\n buildLabels(records, typeSet, forceTraceElements, separator, force);\n\n if (mainTypes.length === 0) {\n if (secondaryTypes.length !== 0)\n throw new Error(\"Non-empty secondary types list while main types list is empty.\");\n return build(new Set(LABEL_TYPE_FULL), true)!;\n }\n\n // Phase 4: search for minimal type set that produces unique labels\n //\n // includedCount = 2\n // * *\n // T0 T1 T2 T3 T4 T5\n // *\n // additionalType = 3\n //\n // Resulting set: T0, T1, T3\n //\n let includedCount = 0;\n let additionalType = -1;\n while (includedCount < mainTypes.length) {\n const currentSet = new Set<string>();\n if (options.includeNativeLabel) currentSet.add(LABEL_TYPE_FULL);\n for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);\n if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);\n\n const candidateResult = build(currentSet, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {\n const minimized = minimizeTypeSet(\n currentSet,\n records,\n stats,\n forceTraceElements,\n options,\n separator,\n );\n return build(minimized, false) ?? throwError(\"Failed to derive unique labels\");\n }\n\n additionalType++;\n if (additionalType >= mainTypes.length) {\n includedCount++;\n additionalType = includedCount;\n }\n }\n\n // Fallback: include all types, then minimize\n const fallbackSet = new Set([...mainTypes, ...secondaryTypes]);\n const minimized = minimizeTypeSet(\n fallbackSet,\n records,\n stats,\n forceTraceElements,\n options,\n separator,\n );\n return build(minimized, true) ?? throwError(\"Failed to derive unique labels\");\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = TraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord<T> = {\n value: T;\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractSpecAndTrace(entry: Entry): {\n spec: PObjectSpec;\n prefixTrace: TraceEntry[] | undefined;\n suffixTrace: TraceEntry[] | undefined;\n} {\n if (\"spec\" in entry && typeof entry.spec === \"object\") {\n return { spec: entry.spec, prefixTrace: entry.prefixTrace, suffixTrace: entry.suffixTrace };\n }\n return { spec: entry as PObjectSpec, prefixTrace: undefined, suffixTrace: undefined };\n}\n\nfunction buildFullTrace(trace: TraceEntry[]): FullTraceEntry[] {\n const result: FullTraceEntry[] = [];\n const occurrences = new Map<string, number>();\n\n for (let i = trace.length - 1; i >= 0; --i) {\n const entry = trace[i];\n const occurrenceIndex = (occurrences.get(entry.type) ?? 0) + 1;\n occurrences.set(entry.type, occurrenceIndex);\n result.push({\n ...entry,\n fullType: `${entry.type}@${occurrenceIndex}`,\n occurrenceIndex,\n });\n }\n\n result.reverse();\n return result;\n}\n\nfunction enrichRecord<T extends Entry>(value: T, options: DeriveLabelsOptions): EnrichedRecord<T> {\n const { spec, prefixTrace, suffixTrace } = extractSpecAndTrace(value);\n\n const label = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace) as\n | CanonicalizedJson<TraceEntry[]>\n | undefined;\n const baseTrace: Trace = traceStr ? (parseJson<Trace>(traceStr) ?? []) : [];\n const trace = [...(prefixTrace ?? []), ...baseTrace, ...(suffixTrace ?? [])];\n\n if (label !== undefined) {\n const labelEntry = { label, type: LABEL_TYPE, importance: -2 };\n if (options.addLabelAsSuffix) trace.push(labelEntry);\n else trace.splice(0, 0, labelEntry);\n }\n\n return { value, fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats<T>(records: EnrichedRecord<T>[]): TypeStats {\n const importances = new Map<string, number>();\n const countByType = new Map<string, number>();\n\n for (const record of records) {\n for (let i = 0; i < record.fullTrace.length; i++) {\n const { fullType, importance: rawImportance } = record.fullTrace[i];\n const importance = rawImportance ?? 0;\n const distance = (record.fullTrace.length - i) * DISTANCE_PENALTY;\n\n countByType.set(fullType, (countByType.get(fullType) ?? 0) + 1);\n importances.set(\n fullType,\n Math.max(importances.get(fullType) ?? Number.NEGATIVE_INFINITY, importance - distance),\n );\n }\n }\n\n return { importances, countByType };\n}\n\nfunction classifyTypes(\n stats: TypeStats,\n totalRecords: number,\n): { mainTypes: string[]; secondaryTypes: string[] } {\n const sorted = [...stats.importances].sort(([, i1], [, i2]) => i2 - i1);\n\n const mainTypes: string[] = [];\n const secondaryTypes: string[] = [];\n\n for (const [typeName] of sorted) {\n if (typeName.endsWith(\"@1\") || stats.countByType.get(typeName) === totalRecords)\n mainTypes.push(typeName);\n else secondaryTypes.push(typeName);\n }\n\n return { mainTypes, secondaryTypes };\n}\n\nfunction buildLabels<T>(\n records: EnrichedRecord<T>[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): WithLabel<T>[] | undefined {\n const result: WithLabel<T>[] = [];\n\n for (const r of records) {\n const parts: string[] = [];\n for (const ft of r.fullTrace) {\n if (includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type)) {\n parts.push(ft.label);\n }\n }\n\n if (parts.length === 0) {\n if (!force) return undefined;\n result.push({ label: \"Unlabeled\", value: r.value });\n continue;\n }\n\n result.push({ label: parts.join(separator), value: r.value });\n }\n\n return result;\n}\n\nfunction countUniqueLabels<T>(result: WithLabel<T>[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result.map((c) => c.label)).size;\n}\n\nfunction minimizeTypeSet<T>(\n typeSet: Set<string>,\n records: EnrichedRecord<T>[],\n stats: TypeStats,\n forceTraceElements: Set<string> | undefined,\n options: DeriveLabelsOptions,\n separator: string,\n): Set<string> {\n const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);\n if (initialResult === undefined) return typeSet;\n\n const targetCardinality = countUniqueLabels(initialResult);\n const result = new Set(typeSet);\n\n const removable = [...result]\n .filter(\n (t) =>\n !forceTraceElements?.has(t.split(\"@\")[0]) &&\n !(options.includeNativeLabel && t === LABEL_TYPE_FULL),\n )\n .sort((a, b) => (stats.importances.get(a) ?? 0) - (stats.importances.get(b) ?? 0));\n\n for (const typeToRemove of removable) {\n const candidate = new Set(result);\n candidate.delete(typeToRemove);\n const candidateResult = buildLabels(records, candidate, forceTraceElements, separator, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= targetCardinality) {\n result.delete(typeToRemove);\n }\n }\n\n return result;\n}\n"],"mappings":";;;;;AASA,MAAM,mBAAmB;AACzB,MAAM,aAAa;AACnB,MAAM,kBAAkB;AA+BxB,SAAgB,qBACd,QACA,UAA+B,EAAE,EACjB;CAChB,MAAM,qBACJ,QAAQ,uBAAuB,UAAa,QAAQ,mBAAmB,SAAS,IAC5E,IAAI,IAAI,QAAQ,mBAAmB,GACnC;CACN,MAAM,YAAY,QAAQ,aAAa;CAGvC,MAAM,UAAU,OAAO,KAAK,MAAM,aAAa,GAAG,QAAQ,CAAC;CAG3D,MAAM,QAAQ,iBAAiB,QAAQ;CAGvC,MAAM,EAAE,WAAW,mBAAmB,cAAc,OAAO,OAAO,OAAO;CAEzE,MAAM,SAAS,SAAsB,UACnC,YAAY,SAAS,SAAS,oBAAoB,WAAW,MAAM;AAErE,KAAI,UAAU,WAAW,GAAG;AAC1B,MAAI,eAAe,WAAW,EAC5B,OAAM,IAAI,MAAM,iEAAiE;AACnF,SAAO,MAAM,IAAI,IAAI,gBAAgB,EAAE,KAAK;;CAa9C,IAAI,gBAAgB;CACpB,IAAI,iBAAiB;AACrB,QAAO,gBAAgB,UAAU,QAAQ;EACvC,MAAM,6BAAa,IAAI,KAAa;AACpC,MAAI,QAAQ,mBAAoB,YAAW,IAAI,gBAAgB;AAC/D,OAAK,IAAI,IAAI,GAAG,IAAI,eAAe,EAAE,EAAG,YAAW,IAAI,UAAU,GAAG;AACpE,MAAI,kBAAkB,EAAG,YAAW,IAAI,UAAU,gBAAgB;EAElE,MAAM,kBAAkB,MAAM,YAAY,MAAM;AAChD,MAAI,oBAAoB,UAAa,kBAAkB,gBAAgB,KAAK,OAAO,OASjF,QAAO,MARW,gBAChB,YACA,SACA,OACA,oBACA,SACA,UACD,EACuB,MAAM,4CAAe,iCAAiC;AAGhF;AACA,MAAI,kBAAkB,UAAU,QAAQ;AACtC;AACA,oBAAiB;;;AAcrB,QAAO,MARW,gBADE,IAAI,IAAI,CAAC,GAAG,WAAW,GAAG,eAAe,CAAC,EAG5D,SACA,OACA,oBACA,SACA,UACD,EACuB,KAAK,4CAAe,iCAAiC;;AAW/E,SAAS,oBAAoB,OAI3B;AACA,KAAI,UAAU,SAAS,OAAO,MAAM,SAAS,SAC3C,QAAO;EAAE,MAAM,MAAM;EAAM,aAAa,MAAM;EAAa,aAAa,MAAM;EAAa;AAE7F,QAAO;EAAE,MAAM;EAAsB,aAAa;EAAW,aAAa;EAAW;;AAGvF,SAAS,eAAe,OAAuC;CAC7D,MAAM,SAA2B,EAAE;CACnC,MAAM,8BAAc,IAAI,KAAqB;AAE7C,MAAK,IAAI,IAAI,MAAM,SAAS,GAAG,KAAK,GAAG,EAAE,GAAG;EAC1C,MAAM,QAAQ,MAAM;EACpB,MAAM,mBAAmB,YAAY,IAAI,MAAM,KAAK,IAAI,KAAK;AAC7D,cAAY,IAAI,MAAM,MAAM,gBAAgB;AAC5C,SAAO,KAAK;GACV,GAAG;GACH,UAAU,GAAG,MAAM,KAAK,GAAG;GAC3B;GACD,CAAC;;AAGJ,QAAO,SAAS;AAChB,QAAO;;AAGT,SAAS,aAA8B,OAAU,SAAiD;CAChG,MAAM,EAAE,MAAM,aAAa,gBAAgB,oBAAoB,MAAM;CAErE,MAAM,4DAAuB,MAAMA,2CAAW,MAAM;CACpD,MAAM,+DAA0B,MAAMA,2CAAW,MAAM;CAGvD,MAAM,YAAmB,0DAA6B,SAAS,IAAI,EAAE,GAAI,EAAE;CAC3E,MAAM,QAAQ;EAAC,GAAI,eAAe,EAAE;EAAG,GAAG;EAAW,GAAI,eAAe,EAAE;EAAE;AAE5E,KAAI,UAAU,QAAW;EACvB,MAAM,aAAa;GAAE;GAAO,MAAM;GAAY,YAAY;GAAI;AAC9D,MAAI,QAAQ,iBAAkB,OAAM,KAAK,WAAW;MAC/C,OAAM,OAAO,GAAG,GAAG,WAAW;;AAGrC,QAAO;EAAE;EAAO,WAAW,eAAe,MAAM;EAAE;;AAQpD,SAAS,iBAAoB,SAAyC;CACpE,MAAM,8BAAc,IAAI,KAAqB;CAC7C,MAAM,8BAAc,IAAI,KAAqB;AAE7C,MAAK,MAAM,UAAU,QACnB,MAAK,IAAI,IAAI,GAAG,IAAI,OAAO,UAAU,QAAQ,KAAK;EAChD,MAAM,EAAE,UAAU,YAAY,kBAAkB,OAAO,UAAU;EACjE,MAAM,aAAa,iBAAiB;EACpC,MAAM,YAAY,OAAO,UAAU,SAAS,KAAK;AAEjD,cAAY,IAAI,WAAW,YAAY,IAAI,SAAS,IAAI,KAAK,EAAE;AAC/D,cAAY,IACV,UACA,KAAK,IAAI,YAAY,IAAI,SAAS,IAAI,OAAO,mBAAmB,aAAa,SAAS,CACvF;;AAIL,QAAO;EAAE;EAAa;EAAa;;AAGrC,SAAS,cACP,OACA,cACmD;CACnD,MAAM,SAAS,CAAC,GAAG,MAAM,YAAY,CAAC,MAAM,GAAG,KAAK,GAAG,QAAQ,KAAK,GAAG;CAEvE,MAAM,YAAsB,EAAE;CAC9B,MAAM,iBAA2B,EAAE;AAEnC,MAAK,MAAM,CAAC,aAAa,OACvB,KAAI,SAAS,SAAS,KAAK,IAAI,MAAM,YAAY,IAAI,SAAS,KAAK,aACjE,WAAU,KAAK,SAAS;KACrB,gBAAe,KAAK,SAAS;AAGpC,QAAO;EAAE;EAAW;EAAgB;;AAGtC,SAAS,YACP,SACA,eACA,oBACA,WACA,OAC4B;CAC5B,MAAM,SAAyB,EAAE;AAEjC,MAAK,MAAM,KAAK,SAAS;EACvB,MAAM,QAAkB,EAAE;AAC1B,OAAK,MAAM,MAAM,EAAE,UACjB,KAAI,cAAc,IAAI,GAAG,SAAS,IAAI,oBAAoB,IAAI,GAAG,KAAK,CACpE,OAAM,KAAK,GAAG,MAAM;AAIxB,MAAI,MAAM,WAAW,GAAG;AACtB,OAAI,CAAC,MAAO,QAAO;AACnB,UAAO,KAAK;IAAE,OAAO;IAAa,OAAO,EAAE;IAAO,CAAC;AACnD;;AAGF,SAAO,KAAK;GAAE,OAAO,MAAM,KAAK,UAAU;GAAE,OAAO,EAAE;GAAO,CAAC;;AAG/D,QAAO;;AAGT,SAAS,kBAAqB,QAA4C;AACxE,KAAI,WAAW,OAAW,QAAO;AACjC,QAAO,IAAI,IAAI,OAAO,KAAK,MAAM,EAAE,MAAM,CAAC,CAAC;;AAG7C,SAAS,gBACP,SACA,SACA,OACA,oBACA,SACA,WACa;CACb,MAAM,gBAAgB,YAAY,SAAS,SAAS,oBAAoB,WAAW,MAAM;AACzF,KAAI,kBAAkB,OAAW,QAAO;CAExC,MAAM,oBAAoB,kBAAkB,cAAc;CAC1D,MAAM,SAAS,IAAI,IAAI,QAAQ;CAE/B,MAAM,YAAY,CAAC,GAAG,OAAO,CAC1B,QACE,MACC,CAAC,oBAAoB,IAAI,EAAE,MAAM,IAAI,CAAC,GAAG,IACzC,EAAE,QAAQ,sBAAsB,MAAM,iBACzC,CACA,MAAM,GAAG,OAAO,MAAM,YAAY,IAAI,EAAE,IAAI,MAAM,MAAM,YAAY,IAAI,EAAE,IAAI,GAAG;AAEpF,MAAK,MAAM,gBAAgB,WAAW;EACpC,MAAM,YAAY,IAAI,IAAI,OAAO;AACjC,YAAU,OAAO,aAAa;EAC9B,MAAM,kBAAkB,YAAY,SAAS,WAAW,oBAAoB,WAAW,MAAM;AAC7F,MAAI,oBAAoB,UAAa,kBAAkB,gBAAgB,IAAI,kBACzE,QAAO,OAAO,aAAa;;AAI/B,QAAO"}
|
|
1
|
+
{"version":3,"file":"derive_distinct_labels.cjs","names":["Annotation"],"sources":["../../src/labels/derive_distinct_labels.ts"],"sourcesContent":["import {\n Annotation,\n parseJson,\n readAnnotation,\n type CanonicalizedJson,\n type PObjectSpec,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\n\nexport type WithLabel<T> = {\n value: T;\n label: string;\n};\n\ntype TraceEntry = {\n id?: string;\n type: string;\n label: string;\n importance?: number;\n};\n\nexport type Trace = TraceEntry[];\n\nexport type Entry =\n | PObjectSpec\n | { spec: PObjectSpec; prefixTrace?: TraceEntry[]; suffixTrace?: TraceEntry[] };\n\nexport type DeriveLabelsOptions = {\n /** Separator to use between label parts (\" / \" by default) */\n separator?: string;\n /** If true, label will be added as suffix (at the end of the generated label). By default label added as a prefix. */\n addLabelAsSuffix?: boolean;\n /** Force inclusion of native column label */\n includeNativeLabel?: boolean;\n /** Trace elements list that will be forced to be included in the label. */\n forceTraceElements?: string[];\n};\n\nexport function deriveDistinctLabels<T extends Entry>(\n values: T[],\n options: DeriveLabelsOptions = {},\n): WithLabel<T>[] {\n const forceTraceElements =\n options.forceTraceElements !== undefined && options.forceTraceElements.length > 0\n ? new Set(options.forceTraceElements)\n : undefined;\n const separator = options.separator ?? \" / \";\n\n // Phase 1: enrich each value with parsed trace\n const records = values.map((v) => enrichRecord(v, options));\n\n // Phase 2: collect global type statistics\n const stats = collectTypeStats(records);\n\n // Phase 3: classify types into main (present everywhere) and secondary\n const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);\n\n const build = (typeSet: Set<string>, force: boolean) =>\n buildLabels(records, typeSet, forceTraceElements, separator, force);\n\n if (mainTypes.length === 0) {\n if (secondaryTypes.length !== 0)\n throw new Error(\"Non-empty secondary types list while main types list is empty.\");\n return build(new Set(LABEL_TYPE_FULL), true)!;\n }\n\n // Phase 4: search for minimal type set that produces unique labels\n //\n // includedCount = 2\n // * *\n // T0 T1 T2 T3 T4 T5\n // *\n // additionalType = 3\n //\n // Resulting set: T0, T1, T3\n //\n let includedCount = 0;\n let additionalType = -1;\n while (includedCount < mainTypes.length) {\n const currentSet = new Set<string>();\n if (options.includeNativeLabel) currentSet.add(LABEL_TYPE_FULL);\n for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);\n if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);\n\n const candidateResult = build(currentSet, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {\n const minimized = minimizeTypeSet(\n currentSet,\n records,\n stats,\n forceTraceElements,\n options,\n separator,\n );\n return build(minimized, false) ?? throwError(\"Failed to derive unique labels\");\n }\n\n additionalType++;\n if (additionalType >= mainTypes.length) {\n includedCount++;\n additionalType = includedCount;\n }\n }\n\n // Fallback: include all types, then minimize\n const fallbackSet = new Set([...mainTypes, ...secondaryTypes]);\n const minimized = minimizeTypeSet(\n fallbackSet,\n records,\n stats,\n forceTraceElements,\n options,\n separator,\n );\n return build(minimized, true) ?? throwError(\"Failed to derive unique labels\");\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = TraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord<T> = {\n value: T;\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractSpecAndTrace(entry: Entry): {\n spec: PObjectSpec;\n prefixTrace: TraceEntry[] | undefined;\n suffixTrace: TraceEntry[] | undefined;\n} {\n if (\"spec\" in entry && typeof entry.spec === \"object\") {\n return { spec: entry.spec, prefixTrace: entry.prefixTrace, suffixTrace: entry.suffixTrace };\n }\n return { spec: entry as PObjectSpec, prefixTrace: undefined, suffixTrace: undefined };\n}\n\nfunction buildFullTrace(trace: TraceEntry[]): FullTraceEntry[] {\n const result: FullTraceEntry[] = [];\n const occurrences = new Map<string, number>();\n\n for (let i = trace.length - 1; i >= 0; --i) {\n const entry = trace[i];\n const occurrenceIndex = (occurrences.get(entry.type) ?? 0) + 1;\n occurrences.set(entry.type, occurrenceIndex);\n result.push({\n ...entry,\n fullType: `${entry.type}@${occurrenceIndex}`,\n occurrenceIndex,\n });\n }\n\n result.reverse();\n return result;\n}\n\nfunction enrichRecord<T extends Entry>(value: T, options: DeriveLabelsOptions): EnrichedRecord<T> {\n const { spec, prefixTrace, suffixTrace } = extractSpecAndTrace(value);\n\n const label = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace) as\n | CanonicalizedJson<TraceEntry[]>\n | undefined;\n const baseTrace: Trace = traceStr ? (parseJson<Trace>(traceStr) ?? []) : [];\n const trace = [...(prefixTrace ?? []), ...baseTrace, ...(suffixTrace ?? [])];\n\n if (label !== undefined) {\n const labelEntry = { label, type: LABEL_TYPE, importance: -2 };\n if (options.addLabelAsSuffix) trace.push(labelEntry);\n else trace.splice(0, 0, labelEntry);\n }\n\n return { value, fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats<T>(records: EnrichedRecord<T>[]): TypeStats {\n const importances = new Map<string, number>();\n const countByType = new Map<string, number>();\n\n for (const record of records) {\n for (let i = 0; i < record.fullTrace.length; i++) {\n const { fullType, importance: rawImportance } = record.fullTrace[i];\n const importance = rawImportance ?? 0;\n const distance = (record.fullTrace.length - i) * DISTANCE_PENALTY;\n\n countByType.set(fullType, (countByType.get(fullType) ?? 0) + 1);\n importances.set(\n fullType,\n Math.max(importances.get(fullType) ?? Number.NEGATIVE_INFINITY, importance - distance),\n );\n }\n }\n\n return { importances, countByType };\n}\n\nfunction classifyTypes(\n stats: TypeStats,\n totalRecords: number,\n): { mainTypes: string[]; secondaryTypes: string[] } {\n const sorted = [...stats.importances].sort(([, i1], [, i2]) => i2 - i1);\n\n const mainTypes: string[] = [];\n const secondaryTypes: string[] = [];\n\n for (const [typeName] of sorted) {\n if (typeName.endsWith(\"@1\") || stats.countByType.get(typeName) === totalRecords)\n mainTypes.push(typeName);\n else secondaryTypes.push(typeName);\n }\n\n return { mainTypes, secondaryTypes };\n}\n\nfunction buildLabels<T>(\n records: EnrichedRecord<T>[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): WithLabel<T>[] | undefined {\n const result: WithLabel<T>[] = [];\n\n for (const r of records) {\n const parts: string[] = [];\n for (const ft of r.fullTrace) {\n if (includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type)) {\n parts.push(ft.label);\n }\n }\n\n if (parts.length === 0) {\n if (!force) return undefined;\n result.push({ label: \"Unlabeled\", value: r.value });\n continue;\n }\n\n result.push({ label: parts.join(separator), value: r.value });\n }\n\n return result;\n}\n\nfunction countUniqueLabels<T>(result: WithLabel<T>[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result.map((c) => c.label)).size;\n}\n\nfunction minimizeTypeSet<T>(\n typeSet: Set<string>,\n records: EnrichedRecord<T>[],\n stats: TypeStats,\n forceTraceElements: Set<string> | undefined,\n options: DeriveLabelsOptions,\n separator: string,\n): Set<string> {\n const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);\n if (initialResult === undefined) return typeSet;\n\n const targetCardinality = countUniqueLabels(initialResult);\n const result = new Set(typeSet);\n\n const removable = [...result]\n .filter(\n (t) =>\n !forceTraceElements?.has(t.split(\"@\")[0]) &&\n !(options.includeNativeLabel && t === LABEL_TYPE_FULL),\n )\n .sort((a, b) => (stats.importances.get(a) ?? 0) - (stats.importances.get(b) ?? 0));\n\n for (const typeToRemove of removable) {\n const candidate = new Set(result);\n candidate.delete(typeToRemove);\n const candidateResult = buildLabels(records, candidate, forceTraceElements, separator, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= targetCardinality) {\n result.delete(typeToRemove);\n }\n }\n\n return result;\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"derive_distinct_labels.d.ts","names":[],"sources":["../../src/labels/derive_distinct_labels.ts"],"mappings":";;;KAaY,SAAA;EACV,KAAA,EAAO,CAAA;EACP,KAAA;AAAA;AAAA,KAGG,UAAA;EACH,EAAA;EACA,IAAA;EACA,KAAA;EACA,UAAA;AAAA;AAAA,KAGU,KAAA,GAAQ,UAAA;AAAA,KAER,KAAA,GACR,WAAA;EACE,IAAA,EAAM,WAAA;EAAa,WAAA,GAAc,UAAA;EAAc,WAAA,GAAc,UAAA;AAAA;AAAA,KAEvD,mBAAA;EAXV,8DAaA,SAAA,WAXA;EAaA,gBAAA,YAbU;EAeV,kBAAA,YAZe;EAcf,kBAAA;AAAA;AAAA,iBAGc,oBAAA,WAA+B,KAAA,CAAA,CAC7C,MAAA,EAAQ,CAAA,IACR,OAAA,GAAS,mBAAA,GACR,SAAA,CAAU,CAAA"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { Annotation, parseJson, readAnnotation } from "@milaboratories/pl-model-common";
|
|
2
2
|
import { throwError } from "@milaboratories/helpers";
|
|
3
|
-
|
|
4
3
|
//#region src/labels/derive_distinct_labels.ts
|
|
5
4
|
const DISTANCE_PENALTY = .001;
|
|
6
5
|
const LABEL_TYPE = "__LABEL__";
|
|
@@ -149,7 +148,7 @@ function minimizeTypeSet(typeSet, records, stats, forceTraceElements, options, s
|
|
|
149
148
|
}
|
|
150
149
|
return result;
|
|
151
150
|
}
|
|
152
|
-
|
|
153
151
|
//#endregion
|
|
154
152
|
export { deriveDistinctLabels };
|
|
153
|
+
|
|
155
154
|
//# sourceMappingURL=derive_distinct_labels.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive_distinct_labels.js","names":[],"sources":["../../src/labels/derive_distinct_labels.ts"],"sourcesContent":["import {\n Annotation,\n parseJson,\n readAnnotation,\n type CanonicalizedJson,\n type PObjectSpec,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\n\nexport type WithLabel<T> = {\n value: T;\n label: string;\n};\n\ntype TraceEntry = {\n id?: string;\n type: string;\n label: string;\n importance?: number;\n};\n\nexport type Trace = TraceEntry[];\n\nexport type Entry =\n | PObjectSpec\n | { spec: PObjectSpec; prefixTrace?: TraceEntry[]; suffixTrace?: TraceEntry[] };\n\nexport type DeriveLabelsOptions = {\n /** Separator to use between label parts (\" / \" by default) */\n separator?: string;\n /** If true, label will be added as suffix (at the end of the generated label). By default label added as a prefix. */\n addLabelAsSuffix?: boolean;\n /** Force inclusion of native column label */\n includeNativeLabel?: boolean;\n /** Trace elements list that will be forced to be included in the label. */\n forceTraceElements?: string[];\n};\n\nexport function deriveDistinctLabels<T extends Entry>(\n values: T[],\n options: DeriveLabelsOptions = {},\n): WithLabel<T>[] {\n const forceTraceElements =\n options.forceTraceElements !== undefined && options.forceTraceElements.length > 0\n ? new Set(options.forceTraceElements)\n : undefined;\n const separator = options.separator ?? \" / \";\n\n // Phase 1: enrich each value with parsed trace\n const records = values.map((v) => enrichRecord(v, options));\n\n // Phase 2: collect global type statistics\n const stats = collectTypeStats(records);\n\n // Phase 3: classify types into main (present everywhere) and secondary\n const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);\n\n const build = (typeSet: Set<string>, force: boolean) =>\n buildLabels(records, typeSet, forceTraceElements, separator, force);\n\n if (mainTypes.length === 0) {\n if (secondaryTypes.length !== 0)\n throw new Error(\"Non-empty secondary types list while main types list is empty.\");\n return build(new Set(LABEL_TYPE_FULL), true)!;\n }\n\n // Phase 4: search for minimal type set that produces unique labels\n //\n // includedCount = 2\n // * *\n // T0 T1 T2 T3 T4 T5\n // *\n // additionalType = 3\n //\n // Resulting set: T0, T1, T3\n //\n let includedCount = 0;\n let additionalType = -1;\n while (includedCount < mainTypes.length) {\n const currentSet = new Set<string>();\n if (options.includeNativeLabel) currentSet.add(LABEL_TYPE_FULL);\n for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);\n if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);\n\n const candidateResult = build(currentSet, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {\n const minimized = minimizeTypeSet(\n currentSet,\n records,\n stats,\n forceTraceElements,\n options,\n separator,\n );\n return build(minimized, false) ?? throwError(\"Failed to derive unique labels\");\n }\n\n additionalType++;\n if (additionalType >= mainTypes.length) {\n includedCount++;\n additionalType = includedCount;\n }\n }\n\n // Fallback: include all types, then minimize\n const fallbackSet = new Set([...mainTypes, ...secondaryTypes]);\n const minimized = minimizeTypeSet(\n fallbackSet,\n records,\n stats,\n forceTraceElements,\n options,\n separator,\n );\n return build(minimized, true) ?? throwError(\"Failed to derive unique labels\");\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = TraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord<T> = {\n value: T;\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractSpecAndTrace(entry: Entry): {\n spec: PObjectSpec;\n prefixTrace: TraceEntry[] | undefined;\n suffixTrace: TraceEntry[] | undefined;\n} {\n if (\"spec\" in entry && typeof entry.spec === \"object\") {\n return { spec: entry.spec, prefixTrace: entry.prefixTrace, suffixTrace: entry.suffixTrace };\n }\n return { spec: entry as PObjectSpec, prefixTrace: undefined, suffixTrace: undefined };\n}\n\nfunction buildFullTrace(trace: TraceEntry[]): FullTraceEntry[] {\n const result: FullTraceEntry[] = [];\n const occurrences = new Map<string, number>();\n\n for (let i = trace.length - 1; i >= 0; --i) {\n const entry = trace[i];\n const occurrenceIndex = (occurrences.get(entry.type) ?? 0) + 1;\n occurrences.set(entry.type, occurrenceIndex);\n result.push({\n ...entry,\n fullType: `${entry.type}@${occurrenceIndex}`,\n occurrenceIndex,\n });\n }\n\n result.reverse();\n return result;\n}\n\nfunction enrichRecord<T extends Entry>(value: T, options: DeriveLabelsOptions): EnrichedRecord<T> {\n const { spec, prefixTrace, suffixTrace } = extractSpecAndTrace(value);\n\n const label = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace) as\n | CanonicalizedJson<TraceEntry[]>\n | undefined;\n const baseTrace: Trace = traceStr ? (parseJson<Trace>(traceStr) ?? []) : [];\n const trace = [...(prefixTrace ?? []), ...baseTrace, ...(suffixTrace ?? [])];\n\n if (label !== undefined) {\n const labelEntry = { label, type: LABEL_TYPE, importance: -2 };\n if (options.addLabelAsSuffix) trace.push(labelEntry);\n else trace.splice(0, 0, labelEntry);\n }\n\n return { value, fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats<T>(records: EnrichedRecord<T>[]): TypeStats {\n const importances = new Map<string, number>();\n const countByType = new Map<string, number>();\n\n for (const record of records) {\n for (let i = 0; i < record.fullTrace.length; i++) {\n const { fullType, importance: rawImportance } = record.fullTrace[i];\n const importance = rawImportance ?? 0;\n const distance = (record.fullTrace.length - i) * DISTANCE_PENALTY;\n\n countByType.set(fullType, (countByType.get(fullType) ?? 0) + 1);\n importances.set(\n fullType,\n Math.max(importances.get(fullType) ?? Number.NEGATIVE_INFINITY, importance - distance),\n );\n }\n }\n\n return { importances, countByType };\n}\n\nfunction classifyTypes(\n stats: TypeStats,\n totalRecords: number,\n): { mainTypes: string[]; secondaryTypes: string[] } {\n const sorted = [...stats.importances].sort(([, i1], [, i2]) => i2 - i1);\n\n const mainTypes: string[] = [];\n const secondaryTypes: string[] = [];\n\n for (const [typeName] of sorted) {\n if (typeName.endsWith(\"@1\") || stats.countByType.get(typeName) === totalRecords)\n mainTypes.push(typeName);\n else secondaryTypes.push(typeName);\n }\n\n return { mainTypes, secondaryTypes };\n}\n\nfunction buildLabels<T>(\n records: EnrichedRecord<T>[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): WithLabel<T>[] | undefined {\n const result: WithLabel<T>[] = [];\n\n for (const r of records) {\n const parts: string[] = [];\n for (const ft of r.fullTrace) {\n if (includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type)) {\n parts.push(ft.label);\n }\n }\n\n if (parts.length === 0) {\n if (!force) return undefined;\n result.push({ label: \"Unlabeled\", value: r.value });\n continue;\n }\n\n result.push({ label: parts.join(separator), value: r.value });\n }\n\n return result;\n}\n\nfunction countUniqueLabels<T>(result: WithLabel<T>[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result.map((c) => c.label)).size;\n}\n\nfunction minimizeTypeSet<T>(\n typeSet: Set<string>,\n records: EnrichedRecord<T>[],\n stats: TypeStats,\n forceTraceElements: Set<string> | undefined,\n options: DeriveLabelsOptions,\n separator: string,\n): Set<string> {\n const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);\n if (initialResult === undefined) return typeSet;\n\n const targetCardinality = countUniqueLabels(initialResult);\n const result = new Set(typeSet);\n\n const removable = [...result]\n .filter(\n (t) =>\n !forceTraceElements?.has(t.split(\"@\")[0]) &&\n !(options.includeNativeLabel && t === LABEL_TYPE_FULL),\n )\n .sort((a, b) => (stats.importances.get(a) ?? 0) - (stats.importances.get(b) ?? 0));\n\n for (const typeToRemove of removable) {\n const candidate = new Set(result);\n candidate.delete(typeToRemove);\n const candidateResult = buildLabels(records, candidate, forceTraceElements, separator, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= targetCardinality) {\n result.delete(typeToRemove);\n }\n }\n\n return result;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"derive_distinct_labels.js","names":[],"sources":["../../src/labels/derive_distinct_labels.ts"],"sourcesContent":["import {\n Annotation,\n parseJson,\n readAnnotation,\n type CanonicalizedJson,\n type PObjectSpec,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\n\nexport type WithLabel<T> = {\n value: T;\n label: string;\n};\n\ntype TraceEntry = {\n id?: string;\n type: string;\n label: string;\n importance?: number;\n};\n\nexport type Trace = TraceEntry[];\n\nexport type Entry =\n | PObjectSpec\n | { spec: PObjectSpec; prefixTrace?: TraceEntry[]; suffixTrace?: TraceEntry[] };\n\nexport type DeriveLabelsOptions = {\n /** Separator to use between label parts (\" / \" by default) */\n separator?: string;\n /** If true, label will be added as suffix (at the end of the generated label). By default label added as a prefix. */\n addLabelAsSuffix?: boolean;\n /** Force inclusion of native column label */\n includeNativeLabel?: boolean;\n /** Trace elements list that will be forced to be included in the label. */\n forceTraceElements?: string[];\n};\n\nexport function deriveDistinctLabels<T extends Entry>(\n values: T[],\n options: DeriveLabelsOptions = {},\n): WithLabel<T>[] {\n const forceTraceElements =\n options.forceTraceElements !== undefined && options.forceTraceElements.length > 0\n ? new Set(options.forceTraceElements)\n : undefined;\n const separator = options.separator ?? \" / \";\n\n // Phase 1: enrich each value with parsed trace\n const records = values.map((v) => enrichRecord(v, options));\n\n // Phase 2: collect global type statistics\n const stats = collectTypeStats(records);\n\n // Phase 3: classify types into main (present everywhere) and secondary\n const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);\n\n const build = (typeSet: Set<string>, force: boolean) =>\n buildLabels(records, typeSet, forceTraceElements, separator, force);\n\n if (mainTypes.length === 0) {\n if (secondaryTypes.length !== 0)\n throw new Error(\"Non-empty secondary types list while main types list is empty.\");\n return build(new Set(LABEL_TYPE_FULL), true)!;\n }\n\n // Phase 4: search for minimal type set that produces unique labels\n //\n // includedCount = 2\n // * *\n // T0 T1 T2 T3 T4 T5\n // *\n // additionalType = 3\n //\n // Resulting set: T0, T1, T3\n //\n let includedCount = 0;\n let additionalType = -1;\n while (includedCount < mainTypes.length) {\n const currentSet = new Set<string>();\n if (options.includeNativeLabel) currentSet.add(LABEL_TYPE_FULL);\n for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);\n if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);\n\n const candidateResult = build(currentSet, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) === values.length) {\n const minimized = minimizeTypeSet(\n currentSet,\n records,\n stats,\n forceTraceElements,\n options,\n separator,\n );\n return build(minimized, false) ?? throwError(\"Failed to derive unique labels\");\n }\n\n additionalType++;\n if (additionalType >= mainTypes.length) {\n includedCount++;\n additionalType = includedCount;\n }\n }\n\n // Fallback: include all types, then minimize\n const fallbackSet = new Set([...mainTypes, ...secondaryTypes]);\n const minimized = minimizeTypeSet(\n fallbackSet,\n records,\n stats,\n forceTraceElements,\n options,\n separator,\n );\n return build(minimized, true) ?? throwError(\"Failed to derive unique labels\");\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = TraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord<T> = {\n value: T;\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractSpecAndTrace(entry: Entry): {\n spec: PObjectSpec;\n prefixTrace: TraceEntry[] | undefined;\n suffixTrace: TraceEntry[] | undefined;\n} {\n if (\"spec\" in entry && typeof entry.spec === \"object\") {\n return { spec: entry.spec, prefixTrace: entry.prefixTrace, suffixTrace: entry.suffixTrace };\n }\n return { spec: entry as PObjectSpec, prefixTrace: undefined, suffixTrace: undefined };\n}\n\nfunction buildFullTrace(trace: TraceEntry[]): FullTraceEntry[] {\n const result: FullTraceEntry[] = [];\n const occurrences = new Map<string, number>();\n\n for (let i = trace.length - 1; i >= 0; --i) {\n const entry = trace[i];\n const occurrenceIndex = (occurrences.get(entry.type) ?? 0) + 1;\n occurrences.set(entry.type, occurrenceIndex);\n result.push({\n ...entry,\n fullType: `${entry.type}@${occurrenceIndex}`,\n occurrenceIndex,\n });\n }\n\n result.reverse();\n return result;\n}\n\nfunction enrichRecord<T extends Entry>(value: T, options: DeriveLabelsOptions): EnrichedRecord<T> {\n const { spec, prefixTrace, suffixTrace } = extractSpecAndTrace(value);\n\n const label = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace) as\n | CanonicalizedJson<TraceEntry[]>\n | undefined;\n const baseTrace: Trace = traceStr ? (parseJson<Trace>(traceStr) ?? []) : [];\n const trace = [...(prefixTrace ?? []), ...baseTrace, ...(suffixTrace ?? [])];\n\n if (label !== undefined) {\n const labelEntry = { label, type: LABEL_TYPE, importance: -2 };\n if (options.addLabelAsSuffix) trace.push(labelEntry);\n else trace.splice(0, 0, labelEntry);\n }\n\n return { value, fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats<T>(records: EnrichedRecord<T>[]): TypeStats {\n const importances = new Map<string, number>();\n const countByType = new Map<string, number>();\n\n for (const record of records) {\n for (let i = 0; i < record.fullTrace.length; i++) {\n const { fullType, importance: rawImportance } = record.fullTrace[i];\n const importance = rawImportance ?? 0;\n const distance = (record.fullTrace.length - i) * DISTANCE_PENALTY;\n\n countByType.set(fullType, (countByType.get(fullType) ?? 0) + 1);\n importances.set(\n fullType,\n Math.max(importances.get(fullType) ?? Number.NEGATIVE_INFINITY, importance - distance),\n );\n }\n }\n\n return { importances, countByType };\n}\n\nfunction classifyTypes(\n stats: TypeStats,\n totalRecords: number,\n): { mainTypes: string[]; secondaryTypes: string[] } {\n const sorted = [...stats.importances].sort(([, i1], [, i2]) => i2 - i1);\n\n const mainTypes: string[] = [];\n const secondaryTypes: string[] = [];\n\n for (const [typeName] of sorted) {\n if (typeName.endsWith(\"@1\") || stats.countByType.get(typeName) === totalRecords)\n mainTypes.push(typeName);\n else secondaryTypes.push(typeName);\n }\n\n return { mainTypes, secondaryTypes };\n}\n\nfunction buildLabels<T>(\n records: EnrichedRecord<T>[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): WithLabel<T>[] | undefined {\n const result: WithLabel<T>[] = [];\n\n for (const r of records) {\n const parts: string[] = [];\n for (const ft of r.fullTrace) {\n if (includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type)) {\n parts.push(ft.label);\n }\n }\n\n if (parts.length === 0) {\n if (!force) return undefined;\n result.push({ label: \"Unlabeled\", value: r.value });\n continue;\n }\n\n result.push({ label: parts.join(separator), value: r.value });\n }\n\n return result;\n}\n\nfunction countUniqueLabels<T>(result: WithLabel<T>[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result.map((c) => c.label)).size;\n}\n\nfunction minimizeTypeSet<T>(\n typeSet: Set<string>,\n records: EnrichedRecord<T>[],\n stats: TypeStats,\n forceTraceElements: Set<string> | undefined,\n options: DeriveLabelsOptions,\n separator: string,\n): Set<string> {\n const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);\n if (initialResult === undefined) return typeSet;\n\n const targetCardinality = countUniqueLabels(initialResult);\n const result = new Set(typeSet);\n\n const removable = [...result]\n .filter(\n (t) =>\n !forceTraceElements?.has(t.split(\"@\")[0]) &&\n !(options.includeNativeLabel && t === LABEL_TYPE_FULL),\n )\n .sort((a, b) => (stats.importances.get(a) ?? 0) - (stats.importances.get(b) ?? 0));\n\n for (const typeToRemove of removable) {\n const candidate = new Set(result);\n candidate.delete(typeToRemove);\n const candidateResult = buildLabels(records, candidate, forceTraceElements, separator, false);\n if (candidateResult !== undefined && countUniqueLabels(candidateResult) >= targetCardinality) {\n result.delete(typeToRemove);\n }\n }\n\n return result;\n}\n"],"mappings":"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"}
|
package/dist/labels/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
require("./derive_distinct_labels.cjs");
|
|
2
|
+
require("./write_labels_to_specs.cjs");
|
package/dist/labels/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import
|
|
2
|
-
import
|
|
1
|
+
import "./derive_distinct_labels.js";
|
|
2
|
+
import "./write_labels_to_specs.js";
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
2
|
let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
|
|
3
|
-
|
|
4
3
|
//#region src/labels/write_labels_to_specs.ts
|
|
5
4
|
function writeLabelsToSpecs(items) {
|
|
6
5
|
for (const { value, label } of items) {
|
|
@@ -9,7 +8,7 @@ function writeLabelsToSpecs(items) {
|
|
|
9
8
|
value.spec.annotations["pl7.app/label/isDerived"] = "true";
|
|
10
9
|
}
|
|
11
10
|
}
|
|
12
|
-
|
|
13
11
|
//#endregion
|
|
14
12
|
exports.writeLabelsToSpecs = writeLabelsToSpecs;
|
|
13
|
+
|
|
15
14
|
//# sourceMappingURL=write_labels_to_specs.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write_labels_to_specs.cjs","names":["Annotation"],"sources":["../../src/labels/write_labels_to_specs.ts"],"sourcesContent":["import { Annotation } from \"@milaboratories/pl-model-common\";\nimport type { ColumnSnapshot } from \"../columns\";\nimport type { WithLabel } from \"./derive_distinct_labels\";\n\nexport function writeLabelsToSpecs(items: WithLabel<ColumnSnapshot>[]): void {\n for (const { value, label } of items) {\n // @ts-expect-error - annotations are mutable at runtime, even if not in the type\n value.spec.annotations = value.spec.annotations ?? {};\n value.spec.annotations[Annotation.Label] = label;\n value.spec.annotations[\"pl7.app/label/isDerived\"] = \"true\";\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"write_labels_to_specs.cjs","names":["Annotation"],"sources":["../../src/labels/write_labels_to_specs.ts"],"sourcesContent":["import { Annotation } from \"@milaboratories/pl-model-common\";\nimport type { ColumnSnapshot } from \"../columns\";\nimport type { WithLabel } from \"./derive_distinct_labels\";\n\nexport function writeLabelsToSpecs(items: WithLabel<ColumnSnapshot>[]): void {\n for (const { value, label } of items) {\n // @ts-expect-error - annotations are mutable at runtime, even if not in the type\n value.spec.annotations = value.spec.annotations ?? {};\n value.spec.annotations[Annotation.Label] = label;\n value.spec.annotations[\"pl7.app/label/isDerived\"] = \"true\";\n }\n}\n"],"mappings":";;;AAIA,SAAgB,mBAAmB,OAA0C;AAC3E,MAAK,MAAM,EAAE,OAAO,WAAW,OAAO;AAEpC,QAAM,KAAK,cAAc,MAAM,KAAK,eAAe,EAAE;AACrD,QAAM,KAAK,YAAYA,gCAAAA,WAAW,SAAS;AAC3C,QAAM,KAAK,YAAY,6BAA6B"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import { WithLabel } from "./derive_distinct_labels.js";
|
|
2
2
|
import { ColumnSnapshot } from "../columns/column_snapshot.js";
|
|
3
|
-
import "../columns/index.js";
|
|
4
|
-
|
|
5
3
|
//#region src/labels/write_labels_to_specs.d.ts
|
|
6
4
|
declare function writeLabelsToSpecs(items: WithLabel<ColumnSnapshot>[]): void;
|
|
7
5
|
//#endregion
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"write_labels_to_specs.d.ts","names":[],"sources":["../../src/labels/write_labels_to_specs.ts"],"mappings":";;;iBAIgB,kBAAA,CAAmB,KAAA,EAAO,SAAA,CAAU,cAAA"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Annotation } from "@milaboratories/pl-model-common";
|
|
2
|
-
|
|
3
2
|
//#region src/labels/write_labels_to_specs.ts
|
|
4
3
|
function writeLabelsToSpecs(items) {
|
|
5
4
|
for (const { value, label } of items) {
|
|
@@ -8,7 +7,7 @@ function writeLabelsToSpecs(items) {
|
|
|
8
7
|
value.spec.annotations["pl7.app/label/isDerived"] = "true";
|
|
9
8
|
}
|
|
10
9
|
}
|
|
11
|
-
|
|
12
10
|
//#endregion
|
|
13
11
|
export { writeLabelsToSpecs };
|
|
12
|
+
|
|
14
13
|
//# sourceMappingURL=write_labels_to_specs.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"write_labels_to_specs.js","names":[],"sources":["../../src/labels/write_labels_to_specs.ts"],"sourcesContent":["import { Annotation } from \"@milaboratories/pl-model-common\";\nimport type { ColumnSnapshot } from \"../columns\";\nimport type { WithLabel } from \"./derive_distinct_labels\";\n\nexport function writeLabelsToSpecs(items: WithLabel<ColumnSnapshot>[]): void {\n for (const { value, label } of items) {\n // @ts-expect-error - annotations are mutable at runtime, even if not in the type\n value.spec.annotations = value.spec.annotations ?? {};\n value.spec.annotations[Annotation.Label] = label;\n value.spec.annotations[\"pl7.app/label/isDerived\"] = \"true\";\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"write_labels_to_specs.js","names":[],"sources":["../../src/labels/write_labels_to_specs.ts"],"sourcesContent":["import { Annotation } from \"@milaboratories/pl-model-common\";\nimport type { ColumnSnapshot } from \"../columns\";\nimport type { WithLabel } from \"./derive_distinct_labels\";\n\nexport function writeLabelsToSpecs(items: WithLabel<ColumnSnapshot>[]): void {\n for (const { value, label } of items) {\n // @ts-expect-error - annotations are mutable at runtime, even if not in the type\n value.spec.annotations = value.spec.annotations ?? {};\n value.spec.annotations[Annotation.Label] = label;\n value.spec.annotations[\"pl7.app/label/isDerived\"] = \"true\";\n }\n}\n"],"mappings":";;AAIA,SAAgB,mBAAmB,OAA0C;AAC3E,MAAK,MAAM,EAAE,OAAO,WAAW,OAAO;AAEpC,QAAM,KAAK,cAAc,MAAM,KAAK,eAAe,EAAE;AACrD,QAAM,KAAK,YAAY,WAAW,SAAS;AAC3C,QAAM,KAAK,YAAY,6BAA6B"}
|
package/dist/package.cjs
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
|
-
|
|
2
1
|
//#region package.json
|
|
3
|
-
var version = "1.63.
|
|
4
|
-
|
|
2
|
+
var version = "1.63.12";
|
|
5
3
|
//#endregion
|
|
6
|
-
Object.defineProperty(exports,
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
4
|
+
Object.defineProperty(exports, "version", {
|
|
5
|
+
enumerable: true,
|
|
6
|
+
get: function() {
|
|
7
|
+
return version;
|
|
8
|
+
}
|
|
11
9
|
});
|
|
10
|
+
|
|
12
11
|
//# sourceMappingURL=package.cjs.map
|
package/dist/package.js
CHANGED
package/dist/pframe.cjs
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
const require_pframe_upgraders = require(
|
|
2
|
-
|
|
1
|
+
const require_pframe_upgraders = require("./render/util/pframe_upgraders.cjs");
|
|
3
2
|
//#region src/pframe.ts
|
|
4
3
|
var PFrameImpl = class {
|
|
5
4
|
constructor(handle) {
|
|
@@ -29,7 +28,7 @@ var PFrameImpl = class {
|
|
|
29
28
|
return platforma;
|
|
30
29
|
}
|
|
31
30
|
};
|
|
32
|
-
|
|
33
31
|
//#endregion
|
|
34
32
|
exports.PFrameImpl = PFrameImpl;
|
|
33
|
+
|
|
35
34
|
//# sourceMappingURL=pframe.cjs.map
|
package/dist/pframe.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pframe.cjs","names":["patchInSetFilters"],"sources":["../src/pframe.ts"],"sourcesContent":["import type {\n CalculateTableDataRequest,\n CalculateTableDataResponse,\n FindColumnsRequest,\n FindColumnsResponse,\n PColumnIdAndSpec,\n PColumnSpec,\n PFrame,\n PFrameHandle,\n PObjectId,\n TableRange,\n UniqueValuesRequest,\n UniqueValuesResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { patchInSetFilters } from \"./render/util/pframe_upgraders\";\n\nexport class PFrameImpl implements PFrame {\n constructor(private readonly handle: PFrameHandle) {}\n\n public async findColumns(request: FindColumnsRequest): Promise<FindColumnsResponse> {\n return await this.getPlatforma().pFrameDriver.findColumns(this.handle, request);\n }\n\n public async getColumnSpec(columnId: PObjectId): Promise<PColumnSpec | null> {\n return await this.getPlatforma().pFrameDriver.getColumnSpec(this.handle, columnId);\n }\n\n public async listColumns(): Promise<PColumnIdAndSpec[]> {\n return await this.getPlatforma().pFrameDriver.listColumns(this.handle);\n }\n\n public async calculateTableData(\n request: CalculateTableDataRequest<PObjectId>,\n range?: TableRange,\n ): Promise<CalculateTableDataResponse> {\n if (!cfgRenderCtx.featureFlags?.pFrameInSetFilterSupport) {\n request = {\n ...request,\n filters: patchInSetFilters(request.filters),\n };\n }\n return await this.getPlatforma().pFrameDriver.calculateTableData(this.handle, request, range);\n }\n\n public async getUniqueValues(request: UniqueValuesRequest): Promise<UniqueValuesResponse> {\n return await this.getPlatforma().pFrameDriver.getUniqueValues(this.handle, request);\n }\n\n private getPlatforma() {\n if (platforma === undefined) {\n throw new Error(\"Platforma instance is not available in the current context.\");\n }\n return platforma;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"pframe.cjs","names":["patchInSetFilters"],"sources":["../src/pframe.ts"],"sourcesContent":["import type {\n CalculateTableDataRequest,\n CalculateTableDataResponse,\n FindColumnsRequest,\n FindColumnsResponse,\n PColumnIdAndSpec,\n PColumnSpec,\n PFrame,\n PFrameHandle,\n PObjectId,\n TableRange,\n UniqueValuesRequest,\n UniqueValuesResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { patchInSetFilters } from \"./render/util/pframe_upgraders\";\n\nexport class PFrameImpl implements PFrame {\n constructor(private readonly handle: PFrameHandle) {}\n\n public async findColumns(request: FindColumnsRequest): Promise<FindColumnsResponse> {\n return await this.getPlatforma().pFrameDriver.findColumns(this.handle, request);\n }\n\n public async getColumnSpec(columnId: PObjectId): Promise<PColumnSpec | null> {\n return await this.getPlatforma().pFrameDriver.getColumnSpec(this.handle, columnId);\n }\n\n public async listColumns(): Promise<PColumnIdAndSpec[]> {\n return await this.getPlatforma().pFrameDriver.listColumns(this.handle);\n }\n\n public async calculateTableData(\n request: CalculateTableDataRequest<PObjectId>,\n range?: TableRange,\n ): Promise<CalculateTableDataResponse> {\n if (!cfgRenderCtx.featureFlags?.pFrameInSetFilterSupport) {\n request = {\n ...request,\n filters: patchInSetFilters(request.filters),\n };\n }\n return await this.getPlatforma().pFrameDriver.calculateTableData(this.handle, request, range);\n }\n\n public async getUniqueValues(request: UniqueValuesRequest): Promise<UniqueValuesResponse> {\n return await this.getPlatforma().pFrameDriver.getUniqueValues(this.handle, request);\n }\n\n private getPlatforma() {\n if (platforma === undefined) {\n throw new Error(\"Platforma instance is not available in the current context.\");\n }\n return platforma;\n }\n}\n"],"mappings":";;AAgBA,IAAa,aAAb,MAA0C;CACxC,YAAY,QAAuC;AAAtB,OAAA,SAAA;;CAE7B,MAAa,YAAY,SAA2D;AAClF,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,YAAY,KAAK,QAAQ,QAAQ;;CAGjF,MAAa,cAAc,UAAkD;AAC3E,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,cAAc,KAAK,QAAQ,SAAS;;CAGpF,MAAa,cAA2C;AACtD,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,YAAY,KAAK,OAAO;;CAGxE,MAAa,mBACX,SACA,OACqC;AACrC,MAAI,CAAC,aAAa,cAAc,yBAC9B,WAAU;GACR,GAAG;GACH,SAASA,yBAAAA,kBAAkB,QAAQ,QAAQ;GAC5C;AAEH,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,mBAAmB,KAAK,QAAQ,SAAS,MAAM;;CAG/F,MAAa,gBAAgB,SAA6D;AACxF,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,gBAAgB,KAAK,QAAQ,QAAQ;;CAGrF,eAAuB;AACrB,MAAI,cAAc,KAAA,EAChB,OAAM,IAAI,MAAM,8DAA8D;AAEhF,SAAO"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pframe.d.ts","names":[],"sources":["../src/pframe.ts"],"mappings":";;;cAgBa,UAAA,YAAsB,MAAA;EAAA,iBACJ,MAAA;cAAA,MAAA,EAAQ,YAAA;EAExB,WAAA,CAAY,OAAA,EAAS,kBAAA,GAAqB,OAAA,CAAQ,mBAAA;EAIlD,aAAA,CAAc,QAAA,EAAU,SAAA,GAAY,OAAA,CAAQ,WAAA;EAI5C,WAAA,CAAA,GAAe,OAAA,CAAQ,gBAAA;EAIvB,kBAAA,CACX,OAAA,EAAS,yBAAA,CAA0B,SAAA,GACnC,KAAA,GAAQ,UAAA,GACP,OAAA,CAAQ,0BAAA;EAUE,eAAA,CAAgB,OAAA,EAAS,mBAAA,GAAsB,OAAA,CAAQ,oBAAA;EAAA,QAI5D,YAAA;AAAA"}
|
package/dist/pframe.js
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { patchInSetFilters } from "./render/util/pframe_upgraders.js";
|
|
2
|
-
|
|
3
2
|
//#region src/pframe.ts
|
|
4
3
|
var PFrameImpl = class {
|
|
5
4
|
constructor(handle) {
|
|
@@ -29,7 +28,7 @@ var PFrameImpl = class {
|
|
|
29
28
|
return platforma;
|
|
30
29
|
}
|
|
31
30
|
};
|
|
32
|
-
|
|
33
31
|
//#endregion
|
|
34
32
|
export { PFrameImpl };
|
|
33
|
+
|
|
35
34
|
//# sourceMappingURL=pframe.js.map
|
package/dist/pframe.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pframe.js","names":[],"sources":["../src/pframe.ts"],"sourcesContent":["import type {\n CalculateTableDataRequest,\n CalculateTableDataResponse,\n FindColumnsRequest,\n FindColumnsResponse,\n PColumnIdAndSpec,\n PColumnSpec,\n PFrame,\n PFrameHandle,\n PObjectId,\n TableRange,\n UniqueValuesRequest,\n UniqueValuesResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { patchInSetFilters } from \"./render/util/pframe_upgraders\";\n\nexport class PFrameImpl implements PFrame {\n constructor(private readonly handle: PFrameHandle) {}\n\n public async findColumns(request: FindColumnsRequest): Promise<FindColumnsResponse> {\n return await this.getPlatforma().pFrameDriver.findColumns(this.handle, request);\n }\n\n public async getColumnSpec(columnId: PObjectId): Promise<PColumnSpec | null> {\n return await this.getPlatforma().pFrameDriver.getColumnSpec(this.handle, columnId);\n }\n\n public async listColumns(): Promise<PColumnIdAndSpec[]> {\n return await this.getPlatforma().pFrameDriver.listColumns(this.handle);\n }\n\n public async calculateTableData(\n request: CalculateTableDataRequest<PObjectId>,\n range?: TableRange,\n ): Promise<CalculateTableDataResponse> {\n if (!cfgRenderCtx.featureFlags?.pFrameInSetFilterSupport) {\n request = {\n ...request,\n filters: patchInSetFilters(request.filters),\n };\n }\n return await this.getPlatforma().pFrameDriver.calculateTableData(this.handle, request, range);\n }\n\n public async getUniqueValues(request: UniqueValuesRequest): Promise<UniqueValuesResponse> {\n return await this.getPlatforma().pFrameDriver.getUniqueValues(this.handle, request);\n }\n\n private getPlatforma() {\n if (platforma === undefined) {\n throw new Error(\"Platforma instance is not available in the current context.\");\n }\n return platforma;\n }\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"pframe.js","names":[],"sources":["../src/pframe.ts"],"sourcesContent":["import type {\n CalculateTableDataRequest,\n CalculateTableDataResponse,\n FindColumnsRequest,\n FindColumnsResponse,\n PColumnIdAndSpec,\n PColumnSpec,\n PFrame,\n PFrameHandle,\n PObjectId,\n TableRange,\n UniqueValuesRequest,\n UniqueValuesResponse,\n} from \"@milaboratories/pl-model-common\";\nimport { patchInSetFilters } from \"./render/util/pframe_upgraders\";\n\nexport class PFrameImpl implements PFrame {\n constructor(private readonly handle: PFrameHandle) {}\n\n public async findColumns(request: FindColumnsRequest): Promise<FindColumnsResponse> {\n return await this.getPlatforma().pFrameDriver.findColumns(this.handle, request);\n }\n\n public async getColumnSpec(columnId: PObjectId): Promise<PColumnSpec | null> {\n return await this.getPlatforma().pFrameDriver.getColumnSpec(this.handle, columnId);\n }\n\n public async listColumns(): Promise<PColumnIdAndSpec[]> {\n return await this.getPlatforma().pFrameDriver.listColumns(this.handle);\n }\n\n public async calculateTableData(\n request: CalculateTableDataRequest<PObjectId>,\n range?: TableRange,\n ): Promise<CalculateTableDataResponse> {\n if (!cfgRenderCtx.featureFlags?.pFrameInSetFilterSupport) {\n request = {\n ...request,\n filters: patchInSetFilters(request.filters),\n };\n }\n return await this.getPlatforma().pFrameDriver.calculateTableData(this.handle, request, range);\n }\n\n public async getUniqueValues(request: UniqueValuesRequest): Promise<UniqueValuesResponse> {\n return await this.getPlatforma().pFrameDriver.getUniqueValues(this.handle, request);\n }\n\n private getPlatforma() {\n if (platforma === undefined) {\n throw new Error(\"Platforma instance is not available in the current context.\");\n }\n return platforma;\n }\n}\n"],"mappings":";;AAgBA,IAAa,aAAb,MAA0C;CACxC,YAAY,QAAuC;AAAtB,OAAA,SAAA;;CAE7B,MAAa,YAAY,SAA2D;AAClF,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,YAAY,KAAK,QAAQ,QAAQ;;CAGjF,MAAa,cAAc,UAAkD;AAC3E,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,cAAc,KAAK,QAAQ,SAAS;;CAGpF,MAAa,cAA2C;AACtD,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,YAAY,KAAK,OAAO;;CAGxE,MAAa,mBACX,SACA,OACqC;AACrC,MAAI,CAAC,aAAa,cAAc,yBAC9B,WAAU;GACR,GAAG;GACH,SAAS,kBAAkB,QAAQ,QAAQ;GAC5C;AAEH,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,mBAAmB,KAAK,QAAQ,SAAS,MAAM;;CAG/F,MAAa,gBAAgB,SAA6D;AACxF,SAAO,MAAM,KAAK,cAAc,CAAC,aAAa,gBAAgB,KAAK,QAAQ,QAAQ;;CAGrF,eAAuB;AACrB,MAAI,cAAc,KAAA,EAChB,OAAM,IAAI,MAAM,8DAA8D;AAEhF,SAAO"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
|
-
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
2
|
let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
|
|
3
|
-
|
|
4
3
|
//#region src/pframe_utils/axes.ts
|
|
5
4
|
/** Create id for column copy with added keys in axes domains */
|
|
6
5
|
const colId = (id, domains, contextDomains) => {
|
|
@@ -106,8 +105,8 @@ function getAdditionalColumnsForColumn(blockAxes, column) {
|
|
|
106
105
|
};
|
|
107
106
|
})];
|
|
108
107
|
}
|
|
109
|
-
|
|
110
108
|
//#endregion
|
|
111
109
|
exports.enrichCompatible = enrichCompatible;
|
|
112
110
|
exports.getAvailableWithLinkersAxes = getAvailableWithLinkersAxes;
|
|
111
|
+
|
|
113
112
|
//# sourceMappingURL=axes.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"axes.cjs","names":["LinkerMap","getColumnIdAndSpec","getAxisId","Annotation"],"sources":["../../src/pframe_utils/axes.ts"],"sourcesContent":["/**\n * Axes utilities for PFrame graph operations.\n *\n * Extracted from PFrameForGraphs to break circular dependency\n * between PFrameForGraphs and columns modules.\n *\n * @module pframe_utils/axes\n */\n\nimport type {\n AxisId,\n AxisSpecNormalized,\n CanonicalizedJson,\n PColumn,\n PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n LinkerMap,\n matchAxisId,\n readAnnotation,\n stringifyJson,\n} from \"@milaboratories/pl-model-common\";\nimport type { PColumnDataUniversal } from \"../render\";\n\nexport type AxesVault = Map<CanonicalizedJson<AxisId>, AxisSpecNormalized>;\n\n/** Create id for column copy with added keys in axes domains */\nconst colId = (\n id: PObjectId,\n domains: (Record<string, string> | undefined)[],\n contextDomains: (Record<string, string> | undefined)[],\n) => {\n let wid = id.toString();\n domains?.forEach((domain) => {\n if (domain) {\n for (const [k, v] of Object.entries(domain)) {\n wid += k;\n wid += v;\n }\n }\n });\n contextDomains?.forEach((contextDomain) => {\n if (contextDomain) {\n for (const [k, v] of Object.entries(contextDomain)) {\n wid += k;\n wid += v;\n }\n }\n });\n return wid;\n};\n\n/** All combinations with 1 key from each list */\nfunction getKeysCombinations(idsLists: AxisId[][]) {\n if (!idsLists.length) {\n return [];\n }\n let result: AxisId[][] = [[]];\n idsLists.forEach((list) => {\n const nextResult: AxisId[][] = [];\n list.forEach((key) => {\n nextResult.push(...result.map((resultItem) => [...resultItem, key]));\n });\n result = nextResult;\n });\n return result;\n}\n\nexport function getAvailableWithLinkersAxes(\n linkerColumns: PColumn<PColumnDataUniversal>[],\n blockAxes: AxesVault,\n): AxesVault {\n const linkerMap = LinkerMap.fromColumns(linkerColumns.map(getColumnIdAndSpec));\n const availableAxes = linkerMap.getReachableByLinkersAxesFromAxesNormalized(\n [...blockAxes.values()],\n (linkerKeyId, sourceAxisId) => matchAxisId(sourceAxisId, linkerKeyId),\n );\n\n return new Map(\n availableAxes.map((axisSpec) => {\n const id = getAxisId(axisSpec);\n return [canonicalizeJson(id), axisSpec];\n }),\n );\n}\n\n/** Add columns with fully compatible axes created from partial compatible ones */\nexport function enrichCompatible<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n columns: T[],\n): T[] {\n return columns.flatMap((column) => getAdditionalColumnsForColumn(blockAxes, column));\n}\n\nfunction getAdditionalColumnsForColumn<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n column: T,\n): T[] {\n const columnAxesIds = column.spec.axesSpec.map(getAxisId);\n\n if (columnAxesIds.every((id) => blockAxes.has(canonicalizeJson(id)))) {\n return [column]; // the column is compatible with its own domains without modifications\n }\n\n // options with different possible domains for every axis of secondary column\n const secondaryIdsOptions = columnAxesIds.map((id) => {\n const result = [];\n for (const [_, mainId] of blockAxes) {\n if (matchAxisId(mainId, id) && !matchAxisId(id, mainId)) {\n result.push(mainId);\n }\n }\n return result;\n });\n // all possible combinations of axes with added domains\n const secondaryIdsVariants = getKeysCombinations(secondaryIdsOptions);\n\n // sets of added to column domain fields\n const allAddedDomainValues = new Set<string>();\n const addedNotToAllVariantsDomainValues = new Set<string>();\n const addedByVariantsDomainValues = secondaryIdsVariants.map((idsList) => {\n const addedSet = new Set<string>();\n idsList.map((axisId, idx) => {\n const d1 = column.spec.axesSpec[idx].domain;\n const d2 = axisId.domain;\n Object.entries(d2 ?? {}).forEach(([key, value]) => {\n if (d1?.[key] === undefined) {\n const item = JSON.stringify([key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n const cd1 = column.spec.axesSpec[idx].contextDomain;\n const cd2 = axisId.contextDomain;\n Object.entries(cd2 ?? {}).forEach(([key, value]) => {\n if (cd1?.[key] === undefined) {\n const item = JSON.stringify([\"ctx:\" + key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n return {\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n };\n });\n return addedSet;\n });\n [...allAddedDomainValues].forEach((addedPart) => {\n if (addedByVariantsDomainValues.some((s) => !s.has(addedPart))) {\n addedNotToAllVariantsDomainValues.add(addedPart);\n }\n });\n\n const additionalColumns = secondaryIdsVariants.map((idsList, idx) => {\n const id = colId(\n column.id,\n idsList.map((id) => id.domain),\n idsList.map((id) => id.contextDomain),\n );\n\n const label = readAnnotation(column.spec, Annotation.Label) ?? \"\";\n const labelDomainPart = [...addedByVariantsDomainValues[idx]]\n .filter((str) => addedNotToAllVariantsDomainValues.has(str))\n .sort()\n .map((v) => JSON.parse(v)?.[1]) // use in labels only domain values, but sort them by key to save the same order in all column variants\n .join(\" / \");\n\n const annotations: Annotation = {\n ...column.spec.annotations,\n [Annotation.Graph.IsVirtual]: stringifyJson(true),\n };\n if (label || labelDomainPart) {\n annotations[Annotation.Label] =\n label && labelDomainPart ? label + \" / \" + labelDomainPart : label + labelDomainPart;\n }\n\n return {\n ...column,\n id: id as PObjectId,\n spec: {\n ...column.spec,\n axesSpec: idsList.map((axisId, idx) => ({\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n })),\n annotations,\n },\n };\n });\n\n return [column, ...additionalColumns];\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"axes.cjs","names":["LinkerMap","getColumnIdAndSpec","getAxisId","Annotation"],"sources":["../../src/pframe_utils/axes.ts"],"sourcesContent":["/**\n * Axes utilities for PFrame graph operations.\n *\n * Extracted from PFrameForGraphs to break circular dependency\n * between PFrameForGraphs and columns modules.\n *\n * @module pframe_utils/axes\n */\n\nimport type {\n AxisId,\n AxisSpecNormalized,\n CanonicalizedJson,\n PColumn,\n PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n LinkerMap,\n matchAxisId,\n readAnnotation,\n stringifyJson,\n} from \"@milaboratories/pl-model-common\";\nimport type { PColumnDataUniversal } from \"../render\";\n\nexport type AxesVault = Map<CanonicalizedJson<AxisId>, AxisSpecNormalized>;\n\n/** Create id for column copy with added keys in axes domains */\nconst colId = (\n id: PObjectId,\n domains: (Record<string, string> | undefined)[],\n contextDomains: (Record<string, string> | undefined)[],\n) => {\n let wid = id.toString();\n domains?.forEach((domain) => {\n if (domain) {\n for (const [k, v] of Object.entries(domain)) {\n wid += k;\n wid += v;\n }\n }\n });\n contextDomains?.forEach((contextDomain) => {\n if (contextDomain) {\n for (const [k, v] of Object.entries(contextDomain)) {\n wid += k;\n wid += v;\n }\n }\n });\n return wid;\n};\n\n/** All combinations with 1 key from each list */\nfunction getKeysCombinations(idsLists: AxisId[][]) {\n if (!idsLists.length) {\n return [];\n }\n let result: AxisId[][] = [[]];\n idsLists.forEach((list) => {\n const nextResult: AxisId[][] = [];\n list.forEach((key) => {\n nextResult.push(...result.map((resultItem) => [...resultItem, key]));\n });\n result = nextResult;\n });\n return result;\n}\n\nexport function getAvailableWithLinkersAxes(\n linkerColumns: PColumn<PColumnDataUniversal>[],\n blockAxes: AxesVault,\n): AxesVault {\n const linkerMap = LinkerMap.fromColumns(linkerColumns.map(getColumnIdAndSpec));\n const availableAxes = linkerMap.getReachableByLinkersAxesFromAxesNormalized(\n [...blockAxes.values()],\n (linkerKeyId, sourceAxisId) => matchAxisId(sourceAxisId, linkerKeyId),\n );\n\n return new Map(\n availableAxes.map((axisSpec) => {\n const id = getAxisId(axisSpec);\n return [canonicalizeJson(id), axisSpec];\n }),\n );\n}\n\n/** Add columns with fully compatible axes created from partial compatible ones */\nexport function enrichCompatible<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n columns: T[],\n): T[] {\n return columns.flatMap((column) => getAdditionalColumnsForColumn(blockAxes, column));\n}\n\nfunction getAdditionalColumnsForColumn<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n column: T,\n): T[] {\n const columnAxesIds = column.spec.axesSpec.map(getAxisId);\n\n if (columnAxesIds.every((id) => blockAxes.has(canonicalizeJson(id)))) {\n return [column]; // the column is compatible with its own domains without modifications\n }\n\n // options with different possible domains for every axis of secondary column\n const secondaryIdsOptions = columnAxesIds.map((id) => {\n const result = [];\n for (const [_, mainId] of blockAxes) {\n if (matchAxisId(mainId, id) && !matchAxisId(id, mainId)) {\n result.push(mainId);\n }\n }\n return result;\n });\n // all possible combinations of axes with added domains\n const secondaryIdsVariants = getKeysCombinations(secondaryIdsOptions);\n\n // sets of added to column domain fields\n const allAddedDomainValues = new Set<string>();\n const addedNotToAllVariantsDomainValues = new Set<string>();\n const addedByVariantsDomainValues = secondaryIdsVariants.map((idsList) => {\n const addedSet = new Set<string>();\n idsList.map((axisId, idx) => {\n const d1 = column.spec.axesSpec[idx].domain;\n const d2 = axisId.domain;\n Object.entries(d2 ?? {}).forEach(([key, value]) => {\n if (d1?.[key] === undefined) {\n const item = JSON.stringify([key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n const cd1 = column.spec.axesSpec[idx].contextDomain;\n const cd2 = axisId.contextDomain;\n Object.entries(cd2 ?? {}).forEach(([key, value]) => {\n if (cd1?.[key] === undefined) {\n const item = JSON.stringify([\"ctx:\" + key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n return {\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n };\n });\n return addedSet;\n });\n [...allAddedDomainValues].forEach((addedPart) => {\n if (addedByVariantsDomainValues.some((s) => !s.has(addedPart))) {\n addedNotToAllVariantsDomainValues.add(addedPart);\n }\n });\n\n const additionalColumns = secondaryIdsVariants.map((idsList, idx) => {\n const id = colId(\n column.id,\n idsList.map((id) => id.domain),\n idsList.map((id) => id.contextDomain),\n );\n\n const label = readAnnotation(column.spec, Annotation.Label) ?? \"\";\n const labelDomainPart = [...addedByVariantsDomainValues[idx]]\n .filter((str) => addedNotToAllVariantsDomainValues.has(str))\n .sort()\n .map((v) => JSON.parse(v)?.[1]) // use in labels only domain values, but sort them by key to save the same order in all column variants\n .join(\" / \");\n\n const annotations: Annotation = {\n ...column.spec.annotations,\n [Annotation.Graph.IsVirtual]: stringifyJson(true),\n };\n if (label || labelDomainPart) {\n annotations[Annotation.Label] =\n label && labelDomainPart ? label + \" / \" + labelDomainPart : label + labelDomainPart;\n }\n\n return {\n ...column,\n id: id as PObjectId,\n spec: {\n ...column.spec,\n axesSpec: idsList.map((axisId, idx) => ({\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n })),\n annotations,\n },\n };\n });\n\n return [column, ...additionalColumns];\n}\n"],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"axes.d.ts","names":[],"sources":["../../src/pframe_utils/axes.ts"],"mappings":";;;;KA4BY,SAAA,GAAY,GAAA,CAAI,iBAAA,CAAkB,MAAA,GAAS,kBAAA;AAAA,iBA4CvC,2BAAA,CACd,aAAA,EAAe,OAAA,CAAQ,oBAAA,KACvB,SAAA,EAAW,SAAA,GACV,SAAA;;iBAgBa,gBAAA,WAA2B,IAAA,CAAK,OAAA,CAAQ,oBAAA,WAAA,CACtD,SAAA,EAAW,SAAA,EACX,OAAA,EAAS,CAAA,KACR,CAAA"}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Annotation, LinkerMap, canonicalizeJson, getAxisId, getColumnIdAndSpec, matchAxisId, readAnnotation, stringifyJson } from "@milaboratories/pl-model-common";
|
|
2
|
-
|
|
3
2
|
//#region src/pframe_utils/axes.ts
|
|
4
3
|
/** Create id for column copy with added keys in axes domains */
|
|
5
4
|
const colId = (id, domains, contextDomains) => {
|
|
@@ -105,7 +104,7 @@ function getAdditionalColumnsForColumn(blockAxes, column) {
|
|
|
105
104
|
};
|
|
106
105
|
})];
|
|
107
106
|
}
|
|
108
|
-
|
|
109
107
|
//#endregion
|
|
110
108
|
export { enrichCompatible, getAvailableWithLinkersAxes };
|
|
109
|
+
|
|
111
110
|
//# sourceMappingURL=axes.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"axes.js","names":[],"sources":["../../src/pframe_utils/axes.ts"],"sourcesContent":["/**\n * Axes utilities for PFrame graph operations.\n *\n * Extracted from PFrameForGraphs to break circular dependency\n * between PFrameForGraphs and columns modules.\n *\n * @module pframe_utils/axes\n */\n\nimport type {\n AxisId,\n AxisSpecNormalized,\n CanonicalizedJson,\n PColumn,\n PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n LinkerMap,\n matchAxisId,\n readAnnotation,\n stringifyJson,\n} from \"@milaboratories/pl-model-common\";\nimport type { PColumnDataUniversal } from \"../render\";\n\nexport type AxesVault = Map<CanonicalizedJson<AxisId>, AxisSpecNormalized>;\n\n/** Create id for column copy with added keys in axes domains */\nconst colId = (\n id: PObjectId,\n domains: (Record<string, string> | undefined)[],\n contextDomains: (Record<string, string> | undefined)[],\n) => {\n let wid = id.toString();\n domains?.forEach((domain) => {\n if (domain) {\n for (const [k, v] of Object.entries(domain)) {\n wid += k;\n wid += v;\n }\n }\n });\n contextDomains?.forEach((contextDomain) => {\n if (contextDomain) {\n for (const [k, v] of Object.entries(contextDomain)) {\n wid += k;\n wid += v;\n }\n }\n });\n return wid;\n};\n\n/** All combinations with 1 key from each list */\nfunction getKeysCombinations(idsLists: AxisId[][]) {\n if (!idsLists.length) {\n return [];\n }\n let result: AxisId[][] = [[]];\n idsLists.forEach((list) => {\n const nextResult: AxisId[][] = [];\n list.forEach((key) => {\n nextResult.push(...result.map((resultItem) => [...resultItem, key]));\n });\n result = nextResult;\n });\n return result;\n}\n\nexport function getAvailableWithLinkersAxes(\n linkerColumns: PColumn<PColumnDataUniversal>[],\n blockAxes: AxesVault,\n): AxesVault {\n const linkerMap = LinkerMap.fromColumns(linkerColumns.map(getColumnIdAndSpec));\n const availableAxes = linkerMap.getReachableByLinkersAxesFromAxesNormalized(\n [...blockAxes.values()],\n (linkerKeyId, sourceAxisId) => matchAxisId(sourceAxisId, linkerKeyId),\n );\n\n return new Map(\n availableAxes.map((axisSpec) => {\n const id = getAxisId(axisSpec);\n return [canonicalizeJson(id), axisSpec];\n }),\n );\n}\n\n/** Add columns with fully compatible axes created from partial compatible ones */\nexport function enrichCompatible<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n columns: T[],\n): T[] {\n return columns.flatMap((column) => getAdditionalColumnsForColumn(blockAxes, column));\n}\n\nfunction getAdditionalColumnsForColumn<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n column: T,\n): T[] {\n const columnAxesIds = column.spec.axesSpec.map(getAxisId);\n\n if (columnAxesIds.every((id) => blockAxes.has(canonicalizeJson(id)))) {\n return [column]; // the column is compatible with its own domains without modifications\n }\n\n // options with different possible domains for every axis of secondary column\n const secondaryIdsOptions = columnAxesIds.map((id) => {\n const result = [];\n for (const [_, mainId] of blockAxes) {\n if (matchAxisId(mainId, id) && !matchAxisId(id, mainId)) {\n result.push(mainId);\n }\n }\n return result;\n });\n // all possible combinations of axes with added domains\n const secondaryIdsVariants = getKeysCombinations(secondaryIdsOptions);\n\n // sets of added to column domain fields\n const allAddedDomainValues = new Set<string>();\n const addedNotToAllVariantsDomainValues = new Set<string>();\n const addedByVariantsDomainValues = secondaryIdsVariants.map((idsList) => {\n const addedSet = new Set<string>();\n idsList.map((axisId, idx) => {\n const d1 = column.spec.axesSpec[idx].domain;\n const d2 = axisId.domain;\n Object.entries(d2 ?? {}).forEach(([key, value]) => {\n if (d1?.[key] === undefined) {\n const item = JSON.stringify([key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n const cd1 = column.spec.axesSpec[idx].contextDomain;\n const cd2 = axisId.contextDomain;\n Object.entries(cd2 ?? {}).forEach(([key, value]) => {\n if (cd1?.[key] === undefined) {\n const item = JSON.stringify([\"ctx:\" + key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n return {\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n };\n });\n return addedSet;\n });\n [...allAddedDomainValues].forEach((addedPart) => {\n if (addedByVariantsDomainValues.some((s) => !s.has(addedPart))) {\n addedNotToAllVariantsDomainValues.add(addedPart);\n }\n });\n\n const additionalColumns = secondaryIdsVariants.map((idsList, idx) => {\n const id = colId(\n column.id,\n idsList.map((id) => id.domain),\n idsList.map((id) => id.contextDomain),\n );\n\n const label = readAnnotation(column.spec, Annotation.Label) ?? \"\";\n const labelDomainPart = [...addedByVariantsDomainValues[idx]]\n .filter((str) => addedNotToAllVariantsDomainValues.has(str))\n .sort()\n .map((v) => JSON.parse(v)?.[1]) // use in labels only domain values, but sort them by key to save the same order in all column variants\n .join(\" / \");\n\n const annotations: Annotation = {\n ...column.spec.annotations,\n [Annotation.Graph.IsVirtual]: stringifyJson(true),\n };\n if (label || labelDomainPart) {\n annotations[Annotation.Label] =\n label && labelDomainPart ? label + \" / \" + labelDomainPart : label + labelDomainPart;\n }\n\n return {\n ...column,\n id: id as PObjectId,\n spec: {\n ...column.spec,\n axesSpec: idsList.map((axisId, idx) => ({\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n })),\n annotations,\n },\n };\n });\n\n return [column, ...additionalColumns];\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"axes.js","names":[],"sources":["../../src/pframe_utils/axes.ts"],"sourcesContent":["/**\n * Axes utilities for PFrame graph operations.\n *\n * Extracted from PFrameForGraphs to break circular dependency\n * between PFrameForGraphs and columns modules.\n *\n * @module pframe_utils/axes\n */\n\nimport type {\n AxisId,\n AxisSpecNormalized,\n CanonicalizedJson,\n PColumn,\n PObjectId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n Annotation,\n canonicalizeJson,\n getAxisId,\n getColumnIdAndSpec,\n LinkerMap,\n matchAxisId,\n readAnnotation,\n stringifyJson,\n} from \"@milaboratories/pl-model-common\";\nimport type { PColumnDataUniversal } from \"../render\";\n\nexport type AxesVault = Map<CanonicalizedJson<AxisId>, AxisSpecNormalized>;\n\n/** Create id for column copy with added keys in axes domains */\nconst colId = (\n id: PObjectId,\n domains: (Record<string, string> | undefined)[],\n contextDomains: (Record<string, string> | undefined)[],\n) => {\n let wid = id.toString();\n domains?.forEach((domain) => {\n if (domain) {\n for (const [k, v] of Object.entries(domain)) {\n wid += k;\n wid += v;\n }\n }\n });\n contextDomains?.forEach((contextDomain) => {\n if (contextDomain) {\n for (const [k, v] of Object.entries(contextDomain)) {\n wid += k;\n wid += v;\n }\n }\n });\n return wid;\n};\n\n/** All combinations with 1 key from each list */\nfunction getKeysCombinations(idsLists: AxisId[][]) {\n if (!idsLists.length) {\n return [];\n }\n let result: AxisId[][] = [[]];\n idsLists.forEach((list) => {\n const nextResult: AxisId[][] = [];\n list.forEach((key) => {\n nextResult.push(...result.map((resultItem) => [...resultItem, key]));\n });\n result = nextResult;\n });\n return result;\n}\n\nexport function getAvailableWithLinkersAxes(\n linkerColumns: PColumn<PColumnDataUniversal>[],\n blockAxes: AxesVault,\n): AxesVault {\n const linkerMap = LinkerMap.fromColumns(linkerColumns.map(getColumnIdAndSpec));\n const availableAxes = linkerMap.getReachableByLinkersAxesFromAxesNormalized(\n [...blockAxes.values()],\n (linkerKeyId, sourceAxisId) => matchAxisId(sourceAxisId, linkerKeyId),\n );\n\n return new Map(\n availableAxes.map((axisSpec) => {\n const id = getAxisId(axisSpec);\n return [canonicalizeJson(id), axisSpec];\n }),\n );\n}\n\n/** Add columns with fully compatible axes created from partial compatible ones */\nexport function enrichCompatible<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n columns: T[],\n): T[] {\n return columns.flatMap((column) => getAdditionalColumnsForColumn(blockAxes, column));\n}\n\nfunction getAdditionalColumnsForColumn<T extends Omit<PColumn<PColumnDataUniversal>, \"data\">>(\n blockAxes: AxesVault,\n column: T,\n): T[] {\n const columnAxesIds = column.spec.axesSpec.map(getAxisId);\n\n if (columnAxesIds.every((id) => blockAxes.has(canonicalizeJson(id)))) {\n return [column]; // the column is compatible with its own domains without modifications\n }\n\n // options with different possible domains for every axis of secondary column\n const secondaryIdsOptions = columnAxesIds.map((id) => {\n const result = [];\n for (const [_, mainId] of blockAxes) {\n if (matchAxisId(mainId, id) && !matchAxisId(id, mainId)) {\n result.push(mainId);\n }\n }\n return result;\n });\n // all possible combinations of axes with added domains\n const secondaryIdsVariants = getKeysCombinations(secondaryIdsOptions);\n\n // sets of added to column domain fields\n const allAddedDomainValues = new Set<string>();\n const addedNotToAllVariantsDomainValues = new Set<string>();\n const addedByVariantsDomainValues = secondaryIdsVariants.map((idsList) => {\n const addedSet = new Set<string>();\n idsList.map((axisId, idx) => {\n const d1 = column.spec.axesSpec[idx].domain;\n const d2 = axisId.domain;\n Object.entries(d2 ?? {}).forEach(([key, value]) => {\n if (d1?.[key] === undefined) {\n const item = JSON.stringify([key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n const cd1 = column.spec.axesSpec[idx].contextDomain;\n const cd2 = axisId.contextDomain;\n Object.entries(cd2 ?? {}).forEach(([key, value]) => {\n if (cd1?.[key] === undefined) {\n const item = JSON.stringify([\"ctx:\" + key, value]);\n addedSet.add(item);\n allAddedDomainValues.add(item);\n }\n });\n return {\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n };\n });\n return addedSet;\n });\n [...allAddedDomainValues].forEach((addedPart) => {\n if (addedByVariantsDomainValues.some((s) => !s.has(addedPart))) {\n addedNotToAllVariantsDomainValues.add(addedPart);\n }\n });\n\n const additionalColumns = secondaryIdsVariants.map((idsList, idx) => {\n const id = colId(\n column.id,\n idsList.map((id) => id.domain),\n idsList.map((id) => id.contextDomain),\n );\n\n const label = readAnnotation(column.spec, Annotation.Label) ?? \"\";\n const labelDomainPart = [...addedByVariantsDomainValues[idx]]\n .filter((str) => addedNotToAllVariantsDomainValues.has(str))\n .sort()\n .map((v) => JSON.parse(v)?.[1]) // use in labels only domain values, but sort them by key to save the same order in all column variants\n .join(\" / \");\n\n const annotations: Annotation = {\n ...column.spec.annotations,\n [Annotation.Graph.IsVirtual]: stringifyJson(true),\n };\n if (label || labelDomainPart) {\n annotations[Annotation.Label] =\n label && labelDomainPart ? label + \" / \" + labelDomainPart : label + labelDomainPart;\n }\n\n return {\n ...column,\n id: id as PObjectId,\n spec: {\n ...column.spec,\n axesSpec: idsList.map((axisId, idx) => ({\n ...axisId,\n annotations: column.spec.axesSpec[idx].annotations,\n })),\n annotations,\n },\n };\n });\n\n return [column, ...additionalColumns];\n}\n"],"mappings":"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"}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
|
|
2
|
-
const require_column_collection = require(
|
|
3
|
-
require(
|
|
4
|
-
const require_axes = require(
|
|
1
|
+
require("../_virtual/_rolldown/runtime.cjs");
|
|
2
|
+
const require_column_collection = require("../render/util/column_collection.cjs");
|
|
3
|
+
require("../render/index.cjs");
|
|
4
|
+
const require_axes = require("./axes.cjs");
|
|
5
5
|
let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
|
|
6
|
-
|
|
7
6
|
//#region src/pframe_utils/columns.ts
|
|
8
7
|
function getAllRelatedColumns(ctx, predicate) {
|
|
9
8
|
const columns = new require_column_collection.PColumnCollection();
|
|
@@ -61,8 +60,8 @@ function getRelatedColumns(ctx, { columns: rootColumns, predicate }) {
|
|
|
61
60
|
}) ?? []).filter((column) => (0, _milaboratories_pl_model_common.isLabelColumn)(column.spec));
|
|
62
61
|
return require_axes.enrichCompatible(blockAxes, [...compatibleWithoutLabels, ...compatibleLabels]);
|
|
63
62
|
}
|
|
64
|
-
|
|
65
63
|
//#endregion
|
|
66
64
|
exports.getAllRelatedColumns = getAllRelatedColumns;
|
|
67
65
|
exports.getRelatedColumns = getRelatedColumns;
|
|
66
|
+
|
|
68
67
|
//# sourceMappingURL=columns.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"columns.cjs","names":["PColumnCollection","enrichCompatible","getAvailableWithLinkersAxes"],"sources":["../../src/pframe_utils/columns.ts"],"sourcesContent":["import type { PColumn, PColumnSpec, PColumnLazy, PFrameDef } from \"@milaboratories/pl-model-common\";\nimport {\n getNormalizedAxesList,\n getAxisId,\n canonicalizeJson,\n isLinkerColumn,\n matchAxisId,\n isLabelColumn,\n} from \"@milaboratories/pl-model-common\";\nimport type { AxesVault } from \"./axes\";\nimport { enrichCompatible, getAvailableWithLinkersAxes } from \"./axes\";\nimport type { RenderCtxBase, PColumnDataUniversal } from \"../render\";\nimport { PColumnCollection } from \"../render\";\n\nexport function getAllRelatedColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n predicate: (spec: PColumnSpec) => boolean,\n): PFrameDef<PColumn<PColumnDataUniversal> | PColumnLazy<undefined | PColumnDataUniversal>> {\n // if current block doesn't produce own columns then use all columns from result pool\n const columns = new PColumnCollection();\n columns.addColumnProvider(ctx.resultPool);\n const allColumns =\n columns.getColumns(predicate, {\n dontWaitAllData: true,\n overrideLabelAnnotation: false,\n }) ?? [];\n\n const allAxes: AxesVault = new Map(\n allColumns\n .flatMap((column) => getNormalizedAxesList(column.spec.axesSpec))\n .map((axisSpec) => {\n const axisId = getAxisId(axisSpec);\n return [canonicalizeJson(axisId), axisSpec];\n }),\n );\n\n // additional columns are duplicates with extra fields in domains for compatibility if there are ones with partial match\n const extendedColumns = enrichCompatible(allAxes, allColumns);\n\n return extendedColumns;\n}\n\nexport function getRelatedColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n {\n columns: rootColumns,\n predicate,\n }: {\n columns: PColumn<PColumnDataUniversal>[];\n predicate: (spec: PColumnSpec) => boolean;\n },\n): PFrameDef<PColumn<PColumnDataUniversal> | PColumnLazy<undefined | PColumnDataUniversal>> {\n // if current block has its own columns then take from result pool only compatible with them\n const columns = new PColumnCollection();\n columns.addColumnProvider(ctx.resultPool);\n columns.addColumns(rootColumns);\n\n // all possible axes from block columns\n const blockAxes: AxesVault = new Map();\n // axes from block columns and compatible result pool columns\n const allAxes: AxesVault = new Map();\n for (const c of rootColumns) {\n for (const spec of getNormalizedAxesList(c.spec.axesSpec)) {\n const aid = getAxisId(spec);\n blockAxes.set(canonicalizeJson(aid), spec);\n allAxes.set(canonicalizeJson(aid), spec);\n }\n }\n\n // all linker columns always go to pFrame - even it's impossible to use some of them they all are hidden\n const linkerColumns =\n columns.getColumns((spec) => predicate(spec) && isLinkerColumn(spec), {\n dontWaitAllData: true,\n }) ?? [];\n const availableWithLinkersAxes = getAvailableWithLinkersAxes(linkerColumns, blockAxes);\n\n // all possible axes from connected linkers\n for (const item of availableWithLinkersAxes) {\n blockAxes.set(...item);\n allAxes.set(...item);\n }\n\n const blockAxesArr = Array.from(blockAxes.values());\n // all compatible with block columns but without label columns\n let compatibleWithoutLabels = (\n columns.getColumns(\n (spec) =>\n predicate(spec) &&\n spec.axesSpec.some((axisSpec) => {\n const axisId = getAxisId(axisSpec);\n return blockAxesArr.some((selectorAxisSpec) =>\n matchAxisId(getAxisId(selectorAxisSpec), axisId),\n );\n }),\n { dontWaitAllData: true, overrideLabelAnnotation: false },\n ) ?? []\n ).filter((column) => !isLabelColumn(column.spec));\n\n // extend axes set for label columns request\n for (const c of compatibleWithoutLabels) {\n for (const spec of getNormalizedAxesList(c.spec.axesSpec)) {\n const aid = getAxisId(spec);\n allAxes.set(canonicalizeJson(aid), spec);\n }\n }\n\n const allAxesArr = Array.from(allAxes.values());\n // extend allowed columns - add columns thad doesn't have axes from block, but have all axes in 'allAxes' list (that means all axes from linkers or from 'hanging' of other selected columns)\n compatibleWithoutLabels = (\n columns.getColumns(\n (spec) =>\n predicate(spec) &&\n spec.axesSpec.every((axisSpec) => {\n const axisId = getAxisId(axisSpec);\n return allAxesArr.some((selectorAxisSpec) =>\n matchAxisId(getAxisId(selectorAxisSpec), axisId),\n );\n }),\n { dontWaitAllData: true, overrideLabelAnnotation: false },\n ) ?? []\n ).filter((column) => !isLabelColumn(column.spec));\n\n // label columns must be compatible with full set of axes - block axes and axes from compatible columns from result pool\n const compatibleLabels = (\n columns.getColumns(\n (spec) =>\n predicate(spec) &&\n spec.axesSpec.some((axisSpec) => {\n const axisId = getAxisId(axisSpec);\n return allAxesArr.some((selectorAxisSpec) =>\n matchAxisId(getAxisId(selectorAxisSpec), axisId),\n );\n }),\n { dontWaitAllData: true, overrideLabelAnnotation: false },\n ) ?? []\n ).filter((column) => isLabelColumn(column.spec));\n\n const compatible = [...compatibleWithoutLabels, ...compatibleLabels];\n\n // additional columns are duplicates with extra fields in domains for compatibility if there are ones with partial match\n const extendedColumns = enrichCompatible(blockAxes, compatible);\n\n return extendedColumns;\n}\n"],"mappings":"
|
|
1
|
+
{"version":3,"file":"columns.cjs","names":["PColumnCollection","enrichCompatible","getAvailableWithLinkersAxes"],"sources":["../../src/pframe_utils/columns.ts"],"sourcesContent":["import type { PColumn, PColumnSpec, PColumnLazy, PFrameDef } from \"@milaboratories/pl-model-common\";\nimport {\n getNormalizedAxesList,\n getAxisId,\n canonicalizeJson,\n isLinkerColumn,\n matchAxisId,\n isLabelColumn,\n} from \"@milaboratories/pl-model-common\";\nimport type { AxesVault } from \"./axes\";\nimport { enrichCompatible, getAvailableWithLinkersAxes } from \"./axes\";\nimport type { RenderCtxBase, PColumnDataUniversal } from \"../render\";\nimport { PColumnCollection } from \"../render\";\n\nexport function getAllRelatedColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n predicate: (spec: PColumnSpec) => boolean,\n): PFrameDef<PColumn<PColumnDataUniversal> | PColumnLazy<undefined | PColumnDataUniversal>> {\n // if current block doesn't produce own columns then use all columns from result pool\n const columns = new PColumnCollection();\n columns.addColumnProvider(ctx.resultPool);\n const allColumns =\n columns.getColumns(predicate, {\n dontWaitAllData: true,\n overrideLabelAnnotation: false,\n }) ?? [];\n\n const allAxes: AxesVault = new Map(\n allColumns\n .flatMap((column) => getNormalizedAxesList(column.spec.axesSpec))\n .map((axisSpec) => {\n const axisId = getAxisId(axisSpec);\n return [canonicalizeJson(axisId), axisSpec];\n }),\n );\n\n // additional columns are duplicates with extra fields in domains for compatibility if there are ones with partial match\n const extendedColumns = enrichCompatible(allAxes, allColumns);\n\n return extendedColumns;\n}\n\nexport function getRelatedColumns<A, U>(\n ctx: RenderCtxBase<A, U>,\n {\n columns: rootColumns,\n predicate,\n }: {\n columns: PColumn<PColumnDataUniversal>[];\n predicate: (spec: PColumnSpec) => boolean;\n },\n): PFrameDef<PColumn<PColumnDataUniversal> | PColumnLazy<undefined | PColumnDataUniversal>> {\n // if current block has its own columns then take from result pool only compatible with them\n const columns = new PColumnCollection();\n columns.addColumnProvider(ctx.resultPool);\n columns.addColumns(rootColumns);\n\n // all possible axes from block columns\n const blockAxes: AxesVault = new Map();\n // axes from block columns and compatible result pool columns\n const allAxes: AxesVault = new Map();\n for (const c of rootColumns) {\n for (const spec of getNormalizedAxesList(c.spec.axesSpec)) {\n const aid = getAxisId(spec);\n blockAxes.set(canonicalizeJson(aid), spec);\n allAxes.set(canonicalizeJson(aid), spec);\n }\n }\n\n // all linker columns always go to pFrame - even it's impossible to use some of them they all are hidden\n const linkerColumns =\n columns.getColumns((spec) => predicate(spec) && isLinkerColumn(spec), {\n dontWaitAllData: true,\n }) ?? [];\n const availableWithLinkersAxes = getAvailableWithLinkersAxes(linkerColumns, blockAxes);\n\n // all possible axes from connected linkers\n for (const item of availableWithLinkersAxes) {\n blockAxes.set(...item);\n allAxes.set(...item);\n }\n\n const blockAxesArr = Array.from(blockAxes.values());\n // all compatible with block columns but without label columns\n let compatibleWithoutLabels = (\n columns.getColumns(\n (spec) =>\n predicate(spec) &&\n spec.axesSpec.some((axisSpec) => {\n const axisId = getAxisId(axisSpec);\n return blockAxesArr.some((selectorAxisSpec) =>\n matchAxisId(getAxisId(selectorAxisSpec), axisId),\n );\n }),\n { dontWaitAllData: true, overrideLabelAnnotation: false },\n ) ?? []\n ).filter((column) => !isLabelColumn(column.spec));\n\n // extend axes set for label columns request\n for (const c of compatibleWithoutLabels) {\n for (const spec of getNormalizedAxesList(c.spec.axesSpec)) {\n const aid = getAxisId(spec);\n allAxes.set(canonicalizeJson(aid), spec);\n }\n }\n\n const allAxesArr = Array.from(allAxes.values());\n // extend allowed columns - add columns thad doesn't have axes from block, but have all axes in 'allAxes' list (that means all axes from linkers or from 'hanging' of other selected columns)\n compatibleWithoutLabels = (\n columns.getColumns(\n (spec) =>\n predicate(spec) &&\n spec.axesSpec.every((axisSpec) => {\n const axisId = getAxisId(axisSpec);\n return allAxesArr.some((selectorAxisSpec) =>\n matchAxisId(getAxisId(selectorAxisSpec), axisId),\n );\n }),\n { dontWaitAllData: true, overrideLabelAnnotation: false },\n ) ?? []\n ).filter((column) => !isLabelColumn(column.spec));\n\n // label columns must be compatible with full set of axes - block axes and axes from compatible columns from result pool\n const compatibleLabels = (\n columns.getColumns(\n (spec) =>\n predicate(spec) &&\n spec.axesSpec.some((axisSpec) => {\n const axisId = getAxisId(axisSpec);\n return allAxesArr.some((selectorAxisSpec) =>\n matchAxisId(getAxisId(selectorAxisSpec), axisId),\n );\n }),\n { dontWaitAllData: true, overrideLabelAnnotation: false },\n ) ?? []\n ).filter((column) => isLabelColumn(column.spec));\n\n const compatible = [...compatibleWithoutLabels, ...compatibleLabels];\n\n // additional columns are duplicates with extra fields in domains for compatibility if there are ones with partial match\n const extendedColumns = enrichCompatible(blockAxes, compatible);\n\n return extendedColumns;\n}\n"],"mappings":"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"}
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { PColumnDataUniversal } from "../render/internal.js";
|
|
2
2
|
import { RenderCtxBase } from "../render/api.js";
|
|
3
|
-
import "../render/index.js";
|
|
4
3
|
import { PColumn, PColumnLazy, PColumnSpec, PFrameDef } from "@milaboratories/pl-model-common";
|
|
5
4
|
|
|
6
5
|
//#region src/pframe_utils/columns.d.ts
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"columns.d.ts","names":[],"sources":["../../src/pframe_utils/columns.ts"],"mappings":";;;;;iBAcgB,oBAAA,MAAA,CACd,GAAA,EAAK,aAAA,CAAc,CAAA,EAAG,CAAA,GACtB,SAAA,GAAY,IAAA,EAAM,WAAA,eACjB,SAAA,CAAU,OAAA,CAAQ,oBAAA,IAAwB,WAAA,aAAwB,oBAAA;AAAA,iBAyBrD,iBAAA,MAAA,CACd,GAAA,EAAK,aAAA,CAAc,CAAA,EAAG,CAAA;EAEpB,OAAA,EAAS,WAAA;EACT;AAAA;EAEA,OAAA,EAAS,OAAA,CAAQ,oBAAA;EACjB,SAAA,GAAY,IAAA,EAAM,WAAA;AAAA,IAEnB,SAAA,CAAU,OAAA,CAAQ,oBAAA,IAAwB,WAAA,aAAwB,oBAAA"}
|
|
@@ -2,7 +2,6 @@ import { PColumnCollection } from "../render/util/column_collection.js";
|
|
|
2
2
|
import "../render/index.js";
|
|
3
3
|
import { enrichCompatible, getAvailableWithLinkersAxes } from "./axes.js";
|
|
4
4
|
import { canonicalizeJson, getAxisId, getNormalizedAxesList, isLabelColumn, isLinkerColumn, matchAxisId } from "@milaboratories/pl-model-common";
|
|
5
|
-
|
|
6
5
|
//#region src/pframe_utils/columns.ts
|
|
7
6
|
function getAllRelatedColumns(ctx, predicate) {
|
|
8
7
|
const columns = new PColumnCollection();
|
|
@@ -60,7 +59,7 @@ function getRelatedColumns(ctx, { columns: rootColumns, predicate }) {
|
|
|
60
59
|
}) ?? []).filter((column) => isLabelColumn(column.spec));
|
|
61
60
|
return enrichCompatible(blockAxes, [...compatibleWithoutLabels, ...compatibleLabels]);
|
|
62
61
|
}
|
|
63
|
-
|
|
64
62
|
//#endregion
|
|
65
63
|
export { getAllRelatedColumns, getRelatedColumns };
|
|
64
|
+
|
|
66
65
|
//# sourceMappingURL=columns.js.map
|