@platforma-sdk/model 1.63.12 → 1.65.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/columns/column_collection_builder.cjs +105 -92
- package/dist/columns/column_collection_builder.cjs.map +1 -1
- package/dist/columns/column_collection_builder.d.ts +13 -12
- package/dist/columns/column_collection_builder.d.ts.map +1 -1
- package/dist/columns/column_collection_builder.js +107 -94
- package/dist/columns/column_collection_builder.js.map +1 -1
- package/dist/columns/column_selector.cjs +8 -80
- package/dist/columns/column_selector.cjs.map +1 -1
- package/dist/columns/column_selector.d.ts +6 -14
- package/dist/columns/column_selector.d.ts.map +1 -1
- package/dist/columns/column_selector.js +6 -77
- package/dist/columns/column_selector.js.map +1 -1
- package/dist/columns/column_snapshot.cjs +3 -3
- package/dist/columns/column_snapshot.cjs.map +1 -1
- package/dist/columns/column_snapshot.d.ts +3 -3
- package/dist/columns/column_snapshot.d.ts.map +1 -1
- package/dist/columns/column_snapshot.js +3 -3
- package/dist/columns/column_snapshot.js.map +1 -1
- package/dist/columns/column_snapshot_provider.cjs +1 -1
- package/dist/columns/column_snapshot_provider.cjs.map +1 -1
- package/dist/columns/column_snapshot_provider.d.ts +8 -8
- package/dist/columns/column_snapshot_provider.d.ts.map +1 -1
- 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.map +1 -1
- package/dist/columns/ctx_column_sources.d.ts +2 -1
- package/dist/columns/ctx_column_sources.d.ts.map +1 -1
- package/dist/columns/ctx_column_sources.js.map +1 -1
- package/dist/columns/expand_by_partition.cjs +106 -0
- package/dist/columns/expand_by_partition.cjs.map +1 -0
- package/dist/columns/expand_by_partition.d.ts +33 -0
- package/dist/columns/expand_by_partition.d.ts.map +1 -0
- package/dist/columns/expand_by_partition.js +105 -0
- package/dist/columns/expand_by_partition.js.map +1 -0
- package/dist/columns/index.cjs +1 -0
- package/dist/columns/index.d.ts +4 -3
- package/dist/columns/index.js +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs +26 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js +25 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs +68 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js +67 -0
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV3.js.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +27 -17
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts +4 -0
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.d.ts.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +28 -18
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +258 -175
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts +37 -21
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.d.ts.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +261 -175
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +64 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts +17 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.d.ts.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js +63 -0
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/index.cjs +2 -1
- package/dist/components/PlDataTable/createPlDataTable/index.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts +2 -1
- package/dist/components/PlDataTable/createPlDataTable/index.d.ts.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/index.js +2 -1
- package/dist/components/PlDataTable/createPlDataTable/index.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs +109 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.d.ts +19 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.d.ts.map +1 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.js +102 -0
- package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -0
- package/dist/components/PlDataTable/index.cjs +3 -1
- package/dist/components/PlDataTable/index.d.ts +5 -3
- package/dist/components/PlDataTable/index.js +3 -1
- package/dist/components/PlDataTable/labels.cjs +25 -11
- package/dist/components/PlDataTable/labels.cjs.map +1 -1
- package/dist/components/PlDataTable/labels.js +25 -11
- package/dist/components/PlDataTable/labels.js.map +1 -1
- package/dist/components/PlDataTable/state-migration.cjs +8 -2
- package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
- package/dist/components/PlDataTable/state-migration.d.ts.map +1 -1
- package/dist/components/PlDataTable/state-migration.js +8 -2
- package/dist/components/PlDataTable/state-migration.js.map +1 -1
- package/dist/components/PlDataTable/typesV5.d.ts +23 -15
- package/dist/components/PlDataTable/typesV5.d.ts.map +1 -1
- package/dist/components/index.cjs +3 -1
- package/dist/components/index.d.ts +4 -2
- package/dist/components/index.js +3 -1
- package/dist/index.cjs +13 -9
- package/dist/index.d.ts +9 -7
- package/dist/index.js +6 -4
- package/dist/labels/derive_distinct_labels.cjs +39 -27
- package/dist/labels/derive_distinct_labels.cjs.map +1 -1
- package/dist/labels/derive_distinct_labels.d.ts +15 -15
- package/dist/labels/derive_distinct_labels.d.ts.map +1 -1
- package/dist/labels/derive_distinct_labels.js +39 -27
- package/dist/labels/derive_distinct_labels.js.map +1 -1
- package/dist/labels/index.cjs +0 -1
- package/dist/labels/index.d.ts +1 -2
- package/dist/labels/index.js +0 -1
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/dist/render/api.cjs +10 -3
- package/dist/render/api.cjs.map +1 -1
- package/dist/render/api.d.ts +2 -2
- package/dist/render/api.d.ts.map +1 -1
- package/dist/render/api.js +10 -3
- package/dist/render/api.js.map +1 -1
- package/dist/render/util/column_collection.cjs +3 -3
- package/dist/render/util/column_collection.cjs.map +1 -1
- package/dist/render/util/column_collection.d.ts.map +1 -1
- package/dist/render/util/column_collection.js +3 -3
- package/dist/render/util/column_collection.js.map +1 -1
- package/dist/render/util/label.cjs +2 -2
- package/dist/render/util/label.cjs.map +1 -1
- package/dist/render/util/label.js +2 -2
- package/dist/render/util/label.js.map +1 -1
- package/dist/render/util/pcolumn_data.cjs.map +1 -1
- package/dist/render/util/pcolumn_data.d.ts +2 -2
- package/dist/render/util/pcolumn_data.d.ts.map +1 -1
- package/dist/render/util/pcolumn_data.js.map +1 -1
- package/package.json +7 -7
- package/src/columns/column_collection_builder.test.ts +40 -27
- package/src/columns/column_collection_builder.ts +176 -131
- package/src/columns/column_selector.test.ts +17 -399
- package/src/columns/column_selector.ts +14 -127
- package/src/columns/column_snapshot.ts +5 -5
- package/src/columns/column_snapshot_provider.ts +11 -10
- package/src/columns/ctx_column_sources.ts +2 -2
- package/src/columns/expand_by_partition.test.ts +4 -4
- package/src/columns/expand_by_partition.ts +4 -3
- package/src/columns/index.ts +1 -0
- package/src/components/PlDataTable/createPlDataTable/createPTableDefV2.ts +42 -0
- package/src/components/PlDataTable/createPlDataTable/createPTableDefV3.ts +89 -0
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts +51 -19
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +500 -313
- package/src/components/PlDataTable/createPlDataTable/discoverColumns.ts +122 -0
- package/src/components/PlDataTable/createPlDataTable/index.ts +4 -2
- package/src/components/PlDataTable/createPlDataTable/utils.test.ts +257 -0
- package/src/components/PlDataTable/createPlDataTable/utils.ts +160 -0
- package/src/components/PlDataTable/index.ts +15 -2
- package/src/components/PlDataTable/labels.ts +29 -18
- package/src/components/PlDataTable/state-migration.ts +6 -1
- package/src/components/PlDataTable/typesV5.ts +25 -12
- package/src/labels/derive_distinct_labels.test.ts +143 -45
- package/src/labels/derive_distinct_labels.ts +102 -49
- package/src/labels/index.ts +0 -1
- package/src/render/api.ts +15 -5
- package/src/render/util/column_collection.ts +4 -3
- package/src/render/util/label.ts +2 -2
- package/src/render/util/pcolumn_data.ts +5 -3
- package/dist/labels/write_labels_to_specs.cjs +0 -14
- package/dist/labels/write_labels_to_specs.cjs.map +0 -1
- package/dist/labels/write_labels_to_specs.d.ts +0 -7
- package/dist/labels/write_labels_to_specs.d.ts.map +0 -1
- package/dist/labels/write_labels_to_specs.js +0 -13
- package/dist/labels/write_labels_to_specs.js.map +0 -1
- package/src/labels/write_labels_to_specs.ts +0 -12
package/dist/index.d.ts
CHANGED
|
@@ -24,7 +24,7 @@ import { CommonFieldTraverseOps, CommonTraversalOps, FieldTraversalStep, FieldTy
|
|
|
24
24
|
import { PColumnDataUniversal, internal_d_exports } from "./render/internal.js";
|
|
25
25
|
import { ExtractFutureRefType, FutureRef } from "./render/future.js";
|
|
26
26
|
import { TreeNodeAccessor, ifDef } from "./render/accessor.js";
|
|
27
|
-
import { DeriveLabelsOptions, Entry, Trace,
|
|
27
|
+
import { DeriveLabelsOptions, Entry, Trace, TraceEntry, deriveDistinctLabels } from "./labels/derive_distinct_labels.js";
|
|
28
28
|
import { deriveLabels } from "./render/util/label.js";
|
|
29
29
|
import { AxisLabelProvider, ColumnProvider, PColumnCollection, PColumnEntryUniversal, PColumnEntryWithLabel, PColumnLazyUniversal, PColumnLazyWithLabel } from "./render/util/column_collection.js";
|
|
30
30
|
import { BlockRenderCtx, InferRenderFunctionReturn, PluginRenderCtx, RenderCtx, RenderCtxBase, RenderCtxLegacy, RenderFunction, RenderFunctionLegacy, ResultPool, UniversalColumnOption, UnwrapFutureRef } from "./render/api.js";
|
|
@@ -44,21 +44,23 @@ import { distillFilterSpec } from "./filters/distill.js";
|
|
|
44
44
|
import { AnnotationSpec, AnnotationSpecUi, ExpressionSpec, FilterSpecUi } from "./annotations/types.js";
|
|
45
45
|
import { convertFilterSpecsToExpressionSpecs } from "./annotations/converter.js";
|
|
46
46
|
import { AnnotationScriptUi, AnnotationStepUi, AnyForm, FilterUi, FilterUiOfType, FilterUiType, FormField, TypeField, TypeFieldRecord, TypeForm, TypeToLiteral, compileAnnotationScript, compileFilter, compileFilters, unreachable } from "./components/PlAnnotations/filters_ui.js";
|
|
47
|
-
import { PTableParamsV2, PlDataTableFilters, PlDataTableFiltersWithMeta, PlDataTableGridStateCore, PlDataTableModel, PlDataTableSheet, PlDataTableSheetState, PlDataTableStateV2CacheEntry, PlDataTableStateV2Normalized, PlTableColumnId, PlTableColumnIdJson } from "./components/PlDataTable/typesV5.js";
|
|
47
|
+
import { PTableParamsV2, PlDataTableFilterMeta, PlDataTableFilterSpecLeaf, PlDataTableFilters, PlDataTableFiltersWithMeta, PlDataTableGridStateCore, PlDataTableModel, PlDataTableSheet, PlDataTableSheetState, PlDataTableStateV2CacheEntry, PlDataTableStateV2Normalized, PlTableColumnId, PlTableColumnIdJson } from "./components/PlDataTable/typesV5.js";
|
|
48
48
|
import { PlDataTableStateV2, createDefaultPTableParams, createPlDataTableStateV2, upgradePlDataTableStateV2 } from "./components/PlDataTable/state-migration.js";
|
|
49
49
|
import { createPlDataTableSheet } from "./components/PlDataTable/createPlDataTableSheet.js";
|
|
50
50
|
import { createPlDataTableV2 } from "./components/PlDataTable/createPlDataTable/createPlDataTableV2.js";
|
|
51
51
|
import { ColumnData, ColumnDataStatus, ColumnSnapshot, createColumnSnapshot, createReadyColumnData } from "./columns/column_snapshot.js";
|
|
52
52
|
import { ArrayColumnProvider, ColumnSnapshotProvider, ColumnSource, OutputColumnProvider, OutputColumnProviderOpts, SnapshotColumnProvider, isColumnSnapshotProvider, toColumnSnapshotProvider } from "./columns/column_snapshot_provider.js";
|
|
53
|
-
import {
|
|
54
|
-
import { AnchoredBuildOptions, AnchoredColumnCollection, AnchoredFindColumnsOptions, BuildOptions, ColumnCollection, ColumnCollectionBuilder, ColumnMatch, FindColumnsOptions, MatchQualifications, MatchVariant, MatchingMode } from "./columns/column_collection_builder.js";
|
|
53
|
+
import { ColumnSelector, RelaxedAxisSelector, RelaxedColumnSelector, RelaxedRecord, RelaxedStringMatchers, StringMatcher, convertColumnSelectorToMultiColumnSelector, convertRelaxedAxisSelectorToMultiAxisSelector, convertRelaxedColumnSelectorToMultiColumnSelector } from "./columns/column_selector.js";
|
|
54
|
+
import { AnchorEntry, AnchoredBuildOptions, AnchoredColumnCollection, AnchoredFindColumnsOptions, BuildOptions, ColumnCollection, ColumnCollectionBuilder, ColumnMatch, FindColumnsOptions, MatchQualifications, MatchVariant, MatchingMode } from "./columns/column_collection_builder.js";
|
|
55
55
|
import { ResultPoolColumnSnapshotProvider, collectCtxColumnSnapshotProviders } from "./columns/ctx_column_sources.js";
|
|
56
|
-
import {
|
|
56
|
+
import { ExpandByPartitionOpts, ExpandByPartitionResult, SplitAxis, expandByPartition } from "./columns/expand_by_partition.js";
|
|
57
|
+
import { discoverTableColumnSnaphots } from "./components/PlDataTable/createPlDataTable/discoverColumns.js";
|
|
58
|
+
import { ColumnMatcher, ColumnOrderRule, ColumnVisibilityRule, ColumnsDisplayOptions, ColumnsSelectorConfig, createPlDataTableOptionsV3, createPlDataTableV3 } from "./components/PlDataTable/createPlDataTable/createPlDataTableV3.js";
|
|
57
59
|
import { createPlDataTable } from "./components/PlDataTable/createPlDataTable/index.js";
|
|
60
|
+
import { getEffectiveVisibility, getOrderPriority, isColumnHidden, isColumnOptional } from "./components/PlDataTable/createPlDataTable/utils.js";
|
|
58
61
|
import { PTableKey, PlSelectionModel, createPlSelectionModel } from "./components/PlSelectionModel.js";
|
|
59
62
|
import { PColumnPredicate, PlMultiSequenceAlignmentColorSchemeOption, PlMultiSequenceAlignmentModel, PlMultiSequenceAlignmentSettings, PlMultiSequenceAlignmentWidget, createRowSelectionColumn } from "./components/PlMultiSequenceAlignment.js";
|
|
60
63
|
import { PFrameImpl } from "./pframe.js";
|
|
61
|
-
import { writeLabelsToSpecs } from "./labels/write_labels_to_specs.js";
|
|
62
64
|
import { fromPlOption, fromPlRef } from "./ref_util.js";
|
|
63
65
|
import { getPlatformaApiVersion, getRawPlatformaInstance } from "./raw_globals.js";
|
|
64
66
|
import { getAllRelatedColumns, getRelatedColumns } from "./pframe_utils/columns.js";
|
|
@@ -67,4 +69,4 @@ import { NodeServiceProxy, buildServices, createNodeServiceProxy } from "./servi
|
|
|
67
69
|
import { getEnvironmentValue } from "./env_value.js";
|
|
68
70
|
export * from "@milaboratories/pl-model-common";
|
|
69
71
|
export * from "@milaboratories/pl-error-like";
|
|
70
|
-
export { ActAnd, ActExtractArchiveAndGetURL, ActFlatten, ActGetBlobContent, ActGetBlobContentAsJson, ActGetBlobContentAsString, ActGetDownloadedBlobContent, ActGetField, ActGetFromCtx, ActGetImmediate, ActGetLastLogs, ActGetLogHandle, ActGetOnDemandBlobContent, ActGetProgressLog, ActGetProgressLogWithInfo, ActGetResourceField, ActGetResourceValueAsJson, ActImportProgress, ActIsEmpty, ActIsolate, ActMakeArray, ActMakeObject, ActMapArrayValues, ActMapRecordValues, ActMapResourceFields, ActNot, ActOr, ActionResult, AnchoredBuildOptions, AnchoredColumnCollection, AnchoredFindColumnsOptions, AndFilter, AnnotationFilter, AnnotationMode, AnnotationScript, AnnotationScript2, AnnotationScriptUi, AnnotationSpec, AnnotationSpecUi, AnnotationStep, AnnotationStepUi, AnyForm, Args, ArrayColumnProvider, AxesVault, AxisLabelProvider, BLOCK_SERVICE_FLAGS, BLOCK_STORAGE_FACADE_VERSION, BlockApiV1, BlockApiV2, BlockConfig, BlockConfigV3, BlockConfigV4, BlockDefaultModelServices, BlockDefaultUiServices, BlockModel, BlockModelInfo, BlockModelV3, BlockRenderCtx, BlockServiceFlags, BlockStatePatch, type BlockStorage, BlockStorageFacade, BlockStorageFacadeCallbacks, BlockStorageFacadeHandles, type BlockStorageSchemaVersion, BuildOptions, CancelSubscription, Cfg, CfgAnd, CfgBlobContent, CfgBlobContentAsJson, CfgBlobContentAsString, CfgDownloadedBlobContent, CfgExtractArchiveAndGetURL, CfgFlatten, CfgGetFromCtx, CfgGetJsonField, CfgGetResourceField, CfgImmediate, CfgImportProgress, CfgIsEmpty, CfgIsolate, CfgLastLogs, CfgLogHandle, CfgMakeArray, CfgMakeObject, CfgMapArrayValues, CfgMapRecordValues, CfgMapResourceFields, CfgNot, CfgOnDemandBlobContent, CfgOr, CfgProgressLog, CfgProgressLogWithInfo, CfgRenderingMode, CfgResourceValueAsJson, Checked, ColumnCollection, ColumnCollectionBuilder, ColumnData, ColumnDataStatus, ColumnMatch, ColumnProvider,
|
|
72
|
+
export { ActAnd, ActExtractArchiveAndGetURL, ActFlatten, ActGetBlobContent, ActGetBlobContentAsJson, ActGetBlobContentAsString, ActGetDownloadedBlobContent, ActGetField, ActGetFromCtx, ActGetImmediate, ActGetLastLogs, ActGetLogHandle, ActGetOnDemandBlobContent, ActGetProgressLog, ActGetProgressLogWithInfo, ActGetResourceField, ActGetResourceValueAsJson, ActImportProgress, ActIsEmpty, ActIsolate, ActMakeArray, ActMakeObject, ActMapArrayValues, ActMapRecordValues, ActMapResourceFields, ActNot, ActOr, ActionResult, AnchorEntry, AnchoredBuildOptions, AnchoredColumnCollection, AnchoredFindColumnsOptions, AndFilter, AnnotationFilter, AnnotationMode, AnnotationScript, AnnotationScript2, AnnotationScriptUi, AnnotationSpec, AnnotationSpecUi, AnnotationStep, AnnotationStepUi, AnyForm, Args, ArrayColumnProvider, AxesVault, AxisLabelProvider, BLOCK_SERVICE_FLAGS, BLOCK_STORAGE_FACADE_VERSION, BlockApiV1, BlockApiV2, BlockConfig, BlockConfigV3, BlockConfigV4, BlockDefaultModelServices, BlockDefaultUiServices, BlockModel, BlockModelInfo, BlockModelV3, BlockRenderCtx, BlockServiceFlags, BlockStatePatch, type BlockStorage, BlockStorageFacade, BlockStorageFacadeCallbacks, BlockStorageFacadeHandles, type BlockStorageSchemaVersion, BuildOptions, CancelSubscription, Cfg, CfgAnd, CfgBlobContent, CfgBlobContentAsJson, CfgBlobContentAsString, CfgDownloadedBlobContent, CfgExtractArchiveAndGetURL, CfgFlatten, CfgGetFromCtx, CfgGetJsonField, CfgGetResourceField, CfgImmediate, CfgImportProgress, CfgIsEmpty, CfgIsolate, CfgLastLogs, CfgLogHandle, CfgMakeArray, CfgMakeObject, CfgMapArrayValues, CfgMapRecordValues, CfgMapResourceFields, CfgNot, CfgOnDemandBlobContent, CfgOr, CfgProgressLog, CfgProgressLogWithInfo, CfgRenderingMode, CfgResourceValueAsJson, Checked, ColumnCollection, ColumnCollectionBuilder, ColumnData, ColumnDataStatus, ColumnMatch, ColumnMatcher, ColumnOrderRule, ColumnProvider, ColumnSelector, ColumnSnapshot, ColumnSnapshotProvider, ColumnSource, ColumnVisibilityRule, ColumnsDisplayOptions, ColumnsSelectorConfig, CommonFieldTraverseOps, CommonTraversalOps, ConfAction, ConfigRenderLambda, ConfigRenderLambdaFlags, ConfigResult, CurrentSdkInfo, DataModel, DataModelBuilder, DeriveHref, DeriveLabelsOptions, Entry, ExpandByPartitionOpts, ExpandByPartitionResult, ExpressionSpec, ExtractAction, ExtractFunctionHandleReturn, ExtractFutureRefType, FieldTraversalStep, FieldType, FilterSpec, FilterSpecLeaf, FilterSpecNode, FilterSpecOfType, FilterSpecType, FilterSpecUi, FilterUi, FilterUiOfType, FilterUiType, FindColumnsOptions, FormField, FutureRef, GetFieldStep, InferArgsType, InferBlockState, InferBlockStatePatch, InferDataType, InferFactoryData, InferFactoryModelServices, InferFactoryOutputs, InferFactoryParams, InferFactoryUiServices, InferHrefType, InferOutputType, InferOutputsFromConfigs, InferOutputsFromLambdas, InferOutputsType, InferPluginData, InferPluginHandle, InferPluginHandles, InferPluginNames, InferRenderFunctionReturn, InferUiState, InferVarTypeSafe, IsNA, It, internal_d_exports as JsRenderInternal, DeriveLabelsOptions as LabelDerivationOps, Log10, MainOutputs, MatchQualifications, MatchVariant, MatchingMode, type MigrateBlockStorageConfig, type MigrationFailure, type MigrationResult, type MigrationSuccess, ModelServices, type MutateStoragePayload, NodeServiceProxy, NotFilter, NumericalComparisonFilter, OptionalPlResourceEntry, OrFilter, OutputColumnProvider, OutputColumnProviderOpts, OutputError, PColumnCollection, PColumnDataUniversal, PColumnEntryUniversal, PColumnEntryWithLabel, PColumnKeyList, PColumnLazyUniversal, PColumnLazyWithLabel, PColumnPredicate, PColumnResourceMapData, PColumnResourceMapEntry, PFrameImpl, POCExtractAction, PTableKey, PTableParamsV2, type ParamsInput, Patch, PatternFilter, PatternPredicate, PatternPredicateContainSubsequence, PatternPredicateEquals, PlDataTableFilterMeta, PlDataTableFilterSpecLeaf, PlDataTableFilters, PlDataTableFiltersWithMeta, PlDataTableGridStateCore, PlDataTableModel, PlDataTableSheet, PlDataTableSheetState, PlDataTableStateV2, PlDataTableStateV2CacheEntry, PlDataTableStateV2Normalized, PlMultiSequenceAlignmentColorSchemeOption, PlMultiSequenceAlignmentModel, PlMultiSequenceAlignmentSettings, PlMultiSequenceAlignmentWidget, PlResourceEntry, PlSelectionModel, PlTableColumnId, PlTableColumnIdJson, Platforma, PlatformaApiVersion, PlatformaExtended, PlatformaFactory, PlatformaSDKVersion, PlatformaV1, PlatformaV2, PlatformaV3, type PluginConfig, type PluginData, PluginDataModel, PluginDataModelBuilder, type PluginDataModelVersions, type PluginFactory, PluginFactoryLike, PluginHandle, PluginInstance, PluginModel, type PluginName, type PluginOutputs, type PluginParams, type PluginRecord, type PluginRegistry, PluginRenderCtx, PrimitiveOrConfig, PrimitiveToCfg, RT_BINARY_PARTITIONED, RT_BINARY_SUPER_PARTITIONED, RT_JSON_PARTITIONED, RT_JSON_SUPER_PARTITIONED, RT_PARQUET_PARTITIONED, RT_PARQUET_SUPER_PARTITIONED, RT_RESOURCE_MAP, RT_RESOURCE_MAP_PARTITIONED, RelaxedAxisSelector, RelaxedColumnSelector, RelaxedRecord, RelaxedStringMatchers, RenderCtx, RenderCtxBase, RenderCtxLegacy, RenderFunction, RenderFunctionLegacy, ResolveCfgType, ResolveModelServices, ResolveUiServices, ResourceTraversalOps, ResourceType, ResultPool, ResultPoolColumnSnapshotProvider, SdkInfo, SimplifiedPColumnSpec, SimplifiedUniversalPColumnEntry, SnapshotColumnProvider, SortedCumulativeSum, Entry as SpecExtractorResult, SplitAxis, StagingOutputs, StdCtx, StdCtxArgsOnly, StringMatcher, Trace, TraceEntry, TransformedColumn, TreeNodeAccessor, TypeField, TypeFieldRecord, TypeForm, TypeToLiteral, TypedConfig, TypedConfigOrConfigLambda, TypedConfigOrString, UiServices, UiState, Unionize, UniversalColumnOption, UnwrapFutureRef, ValueRank, type VersionedData, allPColumnsReady, and, blockServiceNames, buildServices, collectCtxColumnSnapshotProviders, compileAnnotationScript, compileFilter, compileFilters, convertColumnSelectorToMultiColumnSelector, convertFilterSpecsToExpressionSpecs, convertFilterUiToExpressionImpl, convertFilterUiToExpressions, convertOrParsePColumnData, convertRelaxedAxisSelectorToMultiAxisSelector, convertRelaxedColumnSelectorToMultiColumnSelector, createBlockStorage, createColumnSnapshot, createDefaultPTableParams, createNodeServiceProxy, createPFrameForGraphs, createPlDataTable, createPlDataTableOptionsV3, createPlDataTableSheet, createPlDataTableStateV2, createPlDataTableV2, createPlDataTableV3, createPlSelectionModel, createReadyColumnData, createRowSelectionColumn, deriveDataFromStorage, deriveDistinctLabels, deriveLabels, discoverTableColumnSnaphots, distillFilterSpec, downgradeCfgOrLambda, enrichCompatible, expandByPartition, extractArchiveAndGetURL, extractConfig, filterDataInfoEntries, filterSpecToSpecQueryExpr, flatten, fromPlOption, fromPlRef, getAllRelatedColumns, getAvailableWithLinkersAxes, getAxisUniqueValues, getBlobContent, getBlobContentAsJson, getBlobContentAsString, getColumnOrAxisValueLabelsId, getColumnSpecById, getColumnUniqueValues, getColumnsFull, getDownloadedBlobContent, getEffectiveVisibility, getEnvironmentValue, getFromCfg, getImmediate, getImportProgress, getJsonField, getLastLogs, getLogHandle, getOnDemandBlobContent, getOrderPriority, getPartitionKeysList, getPlatformaApiVersion, getPluginData, getProgressLog, getProgressLogWithInfo, getRawPlatformaInstance, getRelatedColumns, getRequestColumnsFromSelectedSources, getResourceField, getResourceValueAsJson, getSingleColumnData, getStorageData, getUniquePartitionKeys, getUniqueSourceValuesWithLabels, ifDef, isBlockStorage, isColumnHidden, isColumnOptional, isColumnSnapshotProvider, isConfigLambda, isEmpty, isHiddenFromGraphColumn, isHiddenFromUIColumn, isPColumnReady, isPluginOutputKey, isolate, makeArray, makeObject, mapArrayValues, mapRecordValues, mapResourceFields, migrateBlockStorage, normalizeBlockStorage, not, or, parsePColumnData, parseResourceMap, pluginOutputKey, pluginOutputPrefix, readOutput, registerFacadeCallbacks, toColumnSnapshotProvider, unreachable, updateStorageData, upgradePlDataTableStateV2, wrapOutputs };
|
package/dist/index.js
CHANGED
|
@@ -35,18 +35,20 @@ import { createDefaultPTableParams, createPlDataTableStateV2, upgradePlDataTable
|
|
|
35
35
|
import { createPlDataTableSheet } from "./components/PlDataTable/createPlDataTableSheet.js";
|
|
36
36
|
import { createColumnSnapshot, createReadyColumnData } from "./columns/column_snapshot.js";
|
|
37
37
|
import { ArrayColumnProvider, OutputColumnProvider, SnapshotColumnProvider, isColumnSnapshotProvider, toColumnSnapshotProvider } from "./columns/column_snapshot_provider.js";
|
|
38
|
-
import {
|
|
38
|
+
import { convertColumnSelectorToMultiColumnSelector, convertRelaxedAxisSelectorToMultiAxisSelector, convertRelaxedColumnSelectorToMultiColumnSelector } from "./columns/column_selector.js";
|
|
39
39
|
import { ColumnCollectionBuilder } from "./columns/column_collection_builder.js";
|
|
40
40
|
import { ResultPoolColumnSnapshotProvider, collectCtxColumnSnapshotProviders } from "./columns/ctx_column_sources.js";
|
|
41
|
+
import { expandByPartition } from "./columns/expand_by_partition.js";
|
|
41
42
|
import "./columns/index.js";
|
|
42
|
-
import {
|
|
43
|
+
import { getEffectiveVisibility, getOrderPriority, isColumnHidden, isColumnOptional } from "./components/PlDataTable/createPlDataTable/utils.js";
|
|
43
44
|
import { createPlDataTableV2 } from "./components/PlDataTable/createPlDataTable/createPlDataTableV2.js";
|
|
45
|
+
import { discoverTableColumnSnaphots } from "./components/PlDataTable/createPlDataTable/discoverColumns.js";
|
|
46
|
+
import { createPlDataTableV3 } from "./components/PlDataTable/createPlDataTable/createPlDataTableV3.js";
|
|
44
47
|
import { createPlDataTable } from "./components/PlDataTable/createPlDataTable/index.js";
|
|
45
48
|
import { createRowSelectionColumn } from "./components/PlMultiSequenceAlignment.js";
|
|
46
49
|
import { createPlSelectionModel } from "./components/PlSelectionModel.js";
|
|
47
50
|
import "./components/index.js";
|
|
48
51
|
import { PFrameImpl } from "./pframe.js";
|
|
49
|
-
import { writeLabelsToSpecs } from "./labels/write_labels_to_specs.js";
|
|
50
52
|
import "./labels/index.js";
|
|
51
53
|
import { fromPlOption, fromPlRef } from "./ref_util.js";
|
|
52
54
|
import { getPlatformaApiVersion, getRawPlatformaInstance } from "./raw_globals.js";
|
|
@@ -58,4 +60,4 @@ import "./services/index.js";
|
|
|
58
60
|
import { getEnvironmentValue } from "./env_value.js";
|
|
59
61
|
export * from "@milaboratories/pl-model-common";
|
|
60
62
|
export * from "@milaboratories/pl-error-like";
|
|
61
|
-
export { Args, ArrayColumnProvider, BLOCK_SERVICE_FLAGS, BLOCK_STORAGE_FACADE_VERSION, BlockModel, BlockModelV3, BlockRenderCtx, BlockStorageFacadeCallbacks, BlockStorageFacadeHandles, ColumnCollectionBuilder, CurrentSdkInfo, DataModel, DataModelBuilder, FutureRef, It, internal_exports as JsRenderInternal, MainOutputs, OutputColumnProvider, OutputError, PColumnCollection, PFrameImpl, PlatformaSDKVersion, PluginDataModel, PluginDataModelBuilder, PluginInstance, PluginModel, PluginRenderCtx, RT_BINARY_PARTITIONED, RT_BINARY_SUPER_PARTITIONED, RT_JSON_PARTITIONED, RT_JSON_SUPER_PARTITIONED, RT_PARQUET_PARTITIONED, RT_PARQUET_SUPER_PARTITIONED, RT_RESOURCE_MAP, RT_RESOURCE_MAP_PARTITIONED, RenderCtxBase, RenderCtxLegacy, ResultPool, ResultPoolColumnSnapshotProvider, SnapshotColumnProvider, StagingOutputs, TreeNodeAccessor, UiState, allPColumnsReady, and, blockServiceNames, buildServices, collectCtxColumnSnapshotProviders,
|
|
63
|
+
export { Args, ArrayColumnProvider, BLOCK_SERVICE_FLAGS, BLOCK_STORAGE_FACADE_VERSION, BlockModel, BlockModelV3, BlockRenderCtx, BlockStorageFacadeCallbacks, BlockStorageFacadeHandles, ColumnCollectionBuilder, CurrentSdkInfo, DataModel, DataModelBuilder, FutureRef, It, internal_exports as JsRenderInternal, MainOutputs, OutputColumnProvider, OutputError, PColumnCollection, PFrameImpl, PlatformaSDKVersion, PluginDataModel, PluginDataModelBuilder, PluginInstance, PluginModel, PluginRenderCtx, RT_BINARY_PARTITIONED, RT_BINARY_SUPER_PARTITIONED, RT_JSON_PARTITIONED, RT_JSON_SUPER_PARTITIONED, RT_PARQUET_PARTITIONED, RT_PARQUET_SUPER_PARTITIONED, RT_RESOURCE_MAP, RT_RESOURCE_MAP_PARTITIONED, RenderCtxBase, RenderCtxLegacy, ResultPool, ResultPoolColumnSnapshotProvider, SnapshotColumnProvider, StagingOutputs, TreeNodeAccessor, UiState, allPColumnsReady, and, blockServiceNames, buildServices, collectCtxColumnSnapshotProviders, compileAnnotationScript, compileFilter, compileFilters, convertColumnSelectorToMultiColumnSelector, convertFilterSpecsToExpressionSpecs, convertFilterUiToExpressionImpl, convertFilterUiToExpressions, convertOrParsePColumnData, convertRelaxedAxisSelectorToMultiAxisSelector, convertRelaxedColumnSelectorToMultiColumnSelector, createBlockStorage, createColumnSnapshot, createDefaultPTableParams, createNodeServiceProxy, createPFrameForGraphs, createPlDataTable, createPlDataTableSheet, createPlDataTableStateV2, createPlDataTableV2, createPlDataTableV3, createPlSelectionModel, createReadyColumnData, createRowSelectionColumn, deriveDataFromStorage, deriveDistinctLabels, deriveLabels, discoverTableColumnSnaphots, distillFilterSpec, downgradeCfgOrLambda, enrichCompatible, expandByPartition, extractArchiveAndGetURL, extractConfig, filterDataInfoEntries, filterSpecToSpecQueryExpr, flatten, fromPlOption, fromPlRef, getAllRelatedColumns, getAvailableWithLinkersAxes, getAxisUniqueValues, getBlobContent, getBlobContentAsJson, getBlobContentAsString, getColumnOrAxisValueLabelsId, getColumnSpecById, getColumnUniqueValues, getColumnsFull, getDownloadedBlobContent, getEffectiveVisibility, getEnvironmentValue, getFromCfg, getImmediate, getImportProgress, getJsonField, getLastLogs, getLogHandle, getOnDemandBlobContent, getOrderPriority, getPartitionKeysList, getPlatformaApiVersion, getPluginData, getProgressLog, getProgressLogWithInfo, getRawPlatformaInstance, getRelatedColumns, getRequestColumnsFromSelectedSources, getResourceField, getResourceValueAsJson, getSingleColumnData, getStorageData, getUniquePartitionKeys, getUniqueSourceValuesWithLabels, ifDef, isBlockStorage, isColumnHidden, isColumnOptional, isColumnSnapshotProvider, isConfigLambda, isEmpty, isHiddenFromGraphColumn, isHiddenFromUIColumn, isPColumnReady, isPluginOutputKey, isolate, makeArray, makeObject, mapArrayValues, mapRecordValues, mapResourceFields, migrateBlockStorage, normalizeBlockStorage, not, or, parsePColumnData, parseResourceMap, pluginOutputKey, pluginOutputPrefix, readOutput, registerFacadeCallbacks, toColumnSnapshotProvider, unreachable, updateStorageData, upgradePlDataTableStateV2, wrapOutputs };
|
|
@@ -1,6 +1,7 @@
|
|
|
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
|
+
let es_toolkit = require("es-toolkit");
|
|
4
5
|
//#region src/labels/derive_distinct_labels.ts
|
|
5
6
|
const DISTANCE_PENALTY = .001;
|
|
6
7
|
const LABEL_TYPE = "__LABEL__";
|
|
@@ -8,13 +9,19 @@ const LABEL_TYPE_FULL = "__LABEL__@1";
|
|
|
8
9
|
function deriveDistinctLabels(values, options = {}) {
|
|
9
10
|
const forceTraceElements = options.forceTraceElements !== void 0 && options.forceTraceElements.length > 0 ? new Set(options.forceTraceElements) : void 0;
|
|
10
11
|
const separator = options.separator ?? " / ";
|
|
12
|
+
const linkerSuffixes = values.map((v, i) => {
|
|
13
|
+
const spec = "spec" in v && typeof v.spec === "object" ? v.spec : v;
|
|
14
|
+
const linkerLabels = extractLinkerLabels(v);
|
|
15
|
+
if (linkerLabels.length === 0) return void 0;
|
|
16
|
+
return (0, es_toolkit.isFunction)(options.linkerLabelFormatter) ? options.linkerLabelFormatter(linkerLabels, spec, i) : `via ${linkerLabels.join(" > ")}`;
|
|
17
|
+
});
|
|
11
18
|
const records = values.map((v) => enrichRecord(v, options));
|
|
12
19
|
const stats = collectTypeStats(records);
|
|
13
20
|
const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);
|
|
14
21
|
const build = (typeSet, force) => buildLabels(records, typeSet, forceTraceElements, separator, force);
|
|
15
22
|
if (mainTypes.length === 0) {
|
|
16
23
|
if (secondaryTypes.length !== 0) throw new Error("Non-empty secondary types list while main types list is empty.");
|
|
17
|
-
return build(new Set(LABEL_TYPE_FULL), true);
|
|
24
|
+
return applyLinkerSuffixes(build(new Set(LABEL_TYPE_FULL), true) ?? (0, _milaboratories_helpers.throwError)("Failed to derive labels using native column labels"), linkerSuffixes);
|
|
18
25
|
}
|
|
19
26
|
let includedCount = 0;
|
|
20
27
|
let additionalType = -1;
|
|
@@ -24,25 +31,37 @@ function deriveDistinctLabels(values, options = {}) {
|
|
|
24
31
|
for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);
|
|
25
32
|
if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);
|
|
26
33
|
const candidateResult = build(currentSet, false);
|
|
27
|
-
if (candidateResult !== void 0 && countUniqueLabels(candidateResult) === values.length) return build(minimizeTypeSet(currentSet, records, stats, forceTraceElements, options, separator), false) ?? (0, _milaboratories_helpers.throwError)("Failed to derive unique labels");
|
|
34
|
+
if (candidateResult !== void 0 && countUniqueLabels(candidateResult) === values.length) return applyLinkerSuffixes(build(minimizeTypeSet(currentSet, records, stats, forceTraceElements, options, separator), false) ?? (0, _milaboratories_helpers.throwError)("Failed to derive unique labels"), linkerSuffixes);
|
|
28
35
|
additionalType++;
|
|
29
36
|
if (additionalType >= mainTypes.length) {
|
|
30
37
|
includedCount++;
|
|
31
38
|
additionalType = includedCount;
|
|
32
39
|
}
|
|
33
40
|
}
|
|
34
|
-
return build(minimizeTypeSet(new Set([...mainTypes, ...secondaryTypes]), records, stats, forceTraceElements, options, separator), true) ?? (0, _milaboratories_helpers.throwError)("Failed to derive unique labels");
|
|
41
|
+
return applyLinkerSuffixes(build(minimizeTypeSet(new Set([...mainTypes, ...secondaryTypes]), records, stats, forceTraceElements, options, separator), true) ?? (0, _milaboratories_helpers.throwError)("Failed to derive unique labels"), linkerSuffixes);
|
|
42
|
+
}
|
|
43
|
+
/** Apply pre-formatted linker suffixes to labels that have them. */
|
|
44
|
+
function applyLinkerSuffixes(labels, suffixes) {
|
|
45
|
+
return labels.map((label, i) => (0, es_toolkit.isNil)(suffixes[i]) ? label : `${label} ${suffixes[i]}`);
|
|
46
|
+
}
|
|
47
|
+
/** Extract linker labels from every step of the linkers path. */
|
|
48
|
+
function extractLinkerLabels(entry) {
|
|
49
|
+
if (!("spec" in entry) || typeof entry.spec !== "object") return [];
|
|
50
|
+
const path = entry.linkerPath;
|
|
51
|
+
if (path === void 0 || path.length === 0) return [];
|
|
52
|
+
const labels = [];
|
|
53
|
+
for (const step of path) {
|
|
54
|
+
const label = ((0, _milaboratories_pl_model_common.readAnnotation)(step.spec, _milaboratories_pl_model_common.Annotation.LinkLabel) ?? (0, _milaboratories_pl_model_common.readAnnotation)(step.spec, _milaboratories_pl_model_common.Annotation.Label))?.trim();
|
|
55
|
+
if (label !== void 0 && label.length > 0) labels.push(label);
|
|
56
|
+
}
|
|
57
|
+
return labels;
|
|
35
58
|
}
|
|
36
59
|
function extractSpecAndTrace(entry) {
|
|
37
|
-
|
|
38
|
-
spec: entry.spec,
|
|
39
|
-
prefixTrace: entry.prefixTrace,
|
|
40
|
-
suffixTrace: entry.suffixTrace
|
|
41
|
-
};
|
|
60
|
+
const isEnriched = "spec" in entry && typeof entry.spec === "object";
|
|
42
61
|
return {
|
|
43
|
-
spec: entry,
|
|
44
|
-
|
|
45
|
-
|
|
62
|
+
spec: isEnriched ? entry.spec : entry,
|
|
63
|
+
extraTrace: isEnriched ? entry.extraTrace : void 0,
|
|
64
|
+
linkerPath: isEnriched ? entry.linkerPath : void 0
|
|
46
65
|
};
|
|
47
66
|
}
|
|
48
67
|
function buildFullTrace(trace) {
|
|
@@ -62,14 +81,16 @@ function buildFullTrace(trace) {
|
|
|
62
81
|
return result;
|
|
63
82
|
}
|
|
64
83
|
function enrichRecord(value, options) {
|
|
65
|
-
const { spec,
|
|
84
|
+
const { spec, extraTrace } = extractSpecAndTrace(value);
|
|
66
85
|
const label = (0, _milaboratories_pl_model_common.readAnnotation)(spec, _milaboratories_pl_model_common.Annotation.Label);
|
|
67
86
|
const traceStr = (0, _milaboratories_pl_model_common.readAnnotation)(spec, _milaboratories_pl_model_common.Annotation.Trace);
|
|
68
87
|
const baseTrace = traceStr ? (0, _milaboratories_pl_model_common.parseJson)(traceStr) ?? [] : [];
|
|
88
|
+
const prefixExtra = extraTrace?.filter((e) => e.position === "prefix") ?? [];
|
|
89
|
+
const suffixExtra = extraTrace?.filter((e) => e.position !== "prefix") ?? [];
|
|
69
90
|
const trace = [
|
|
70
|
-
...
|
|
91
|
+
...prefixExtra,
|
|
71
92
|
...baseTrace,
|
|
72
|
-
...
|
|
93
|
+
...suffixExtra
|
|
73
94
|
];
|
|
74
95
|
if (label !== void 0) {
|
|
75
96
|
const labelEntry = {
|
|
@@ -80,10 +101,7 @@ function enrichRecord(value, options) {
|
|
|
80
101
|
if (options.addLabelAsSuffix) trace.push(labelEntry);
|
|
81
102
|
else trace.splice(0, 0, labelEntry);
|
|
82
103
|
}
|
|
83
|
-
return {
|
|
84
|
-
value,
|
|
85
|
-
fullTrace: buildFullTrace(trace)
|
|
86
|
-
};
|
|
104
|
+
return { fullTrace: buildFullTrace(trace) };
|
|
87
105
|
}
|
|
88
106
|
function collectTypeStats(records) {
|
|
89
107
|
const importances = /* @__PURE__ */ new Map();
|
|
@@ -118,22 +136,16 @@ function buildLabels(records, includedTypes, forceTraceElements, separator, forc
|
|
|
118
136
|
for (const ft of r.fullTrace) if (includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type)) parts.push(ft.label);
|
|
119
137
|
if (parts.length === 0) {
|
|
120
138
|
if (!force) return void 0;
|
|
121
|
-
result.push(
|
|
122
|
-
label: "Unlabeled",
|
|
123
|
-
value: r.value
|
|
124
|
-
});
|
|
139
|
+
result.push("Unlabeled");
|
|
125
140
|
continue;
|
|
126
141
|
}
|
|
127
|
-
result.push(
|
|
128
|
-
label: parts.join(separator),
|
|
129
|
-
value: r.value
|
|
130
|
-
});
|
|
142
|
+
result.push(parts.join(separator));
|
|
131
143
|
}
|
|
132
144
|
return result;
|
|
133
145
|
}
|
|
134
146
|
function countUniqueLabels(result) {
|
|
135
147
|
if (result === void 0) return 0;
|
|
136
|
-
return new Set(result
|
|
148
|
+
return new Set(result).size;
|
|
137
149
|
}
|
|
138
150
|
function minimizeTypeSet(typeSet, records, stats, forceTraceElements, options, separator) {
|
|
139
151
|
const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);
|
|
@@ -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":"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"}
|
|
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 PObjectSpec,\n type StringifiedJson,\n type Trace,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\n\nexport type { Trace, TraceEntry } from \"@milaboratories/pl-model-common\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\n\n/** SDK-internal trace shape — adds fields used by this algorithm only, not part of the on-disk contract. */\ntype ExtendedTraceEntry = Trace[number] & {\n importance?: number;\n position?: \"prefix\" | \"suffix\";\n};\n\nexport type Entry =\n | PObjectSpec\n | {\n spec: PObjectSpec;\n /** Extra trace entries merged with the base trace from annotations. */\n extraTrace?: ExtendedTraceEntry[];\n /** Linker steps traversed to discover this column; used to append \"via $linkLabel\" to derived labels. */\n linkerPath?: { spec: PObjectSpec }[];\n };\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 /** Custom formatter for linker path suffix. Receives the array of linker labels from the full traversal chain,\n * the column spec, and the column index.\n * If returns undefined, no linker suffix is appended. By default labels are joined with \" > \" and prefixed with \"via \". */\n linkerLabelFormatter?: (\n linkerLabels: string[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n};\n\nexport function deriveDistinctLabels(values: Entry[], options: DeriveLabelsOptions = {}): string[] {\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 // Collect per-entry linker suffixes before disambiguation\n const linkerSuffixes = values.map((v, i) => {\n const spec = \"spec\" in v && typeof v.spec === \"object\" ? v.spec : (v as PObjectSpec);\n const linkerLabels = extractLinkerLabels(v);\n if (linkerLabels.length === 0) return undefined;\n return isFunction(options.linkerLabelFormatter)\n ? options.linkerLabelFormatter(linkerLabels, spec, i)\n : `via ${linkerLabels.join(\" > \")}`;\n });\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\n return applyLinkerSuffixes(\n build(new Set(LABEL_TYPE_FULL), true) ??\n throwError(\"Failed to derive labels using native column labels\"),\n linkerSuffixes,\n );\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 applyLinkerSuffixes(\n build(minimized, false) ?? throwError(\"Failed to derive unique labels\"),\n linkerSuffixes,\n );\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 applyLinkerSuffixes(\n build(minimized, true) ?? throwError(\"Failed to derive unique labels\"),\n linkerSuffixes,\n );\n}\n\n/** Apply pre-formatted linker suffixes to labels that have them. */\nfunction applyLinkerSuffixes(labels: string[], suffixes: (string | undefined)[]): string[] {\n return labels.map((label, i) => (isNil(suffixes[i]) ? label : `${label} ${suffixes[i]}`));\n}\n\n/** Extract linker labels from every step of the linkers path. */\nfunction extractLinkerLabels(entry: Entry): string[] {\n if (!(\"spec\" in entry) || typeof entry.spec !== \"object\") return [];\n const path = entry.linkerPath;\n if (path === undefined || path.length === 0) return [];\n const labels: string[] = [];\n for (const step of path) {\n const label = (\n readAnnotation(step.spec, Annotation.LinkLabel) ?? readAnnotation(step.spec, Annotation.Label)\n )?.trim();\n if (label !== undefined && label.length > 0) {\n labels.push(label);\n }\n }\n return labels;\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = ExtendedTraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord = {\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractSpecAndTrace(entry: Entry): {\n spec: PObjectSpec;\n extraTrace: ExtendedTraceEntry[] | undefined;\n linkerPath: { spec: PObjectSpec }[] | undefined;\n} {\n const isEnriched = \"spec\" in entry && typeof entry.spec === \"object\";\n return {\n spec: isEnriched ? entry.spec : (entry as PObjectSpec),\n extraTrace: isEnriched ? entry.extraTrace : undefined,\n linkerPath: isEnriched ? entry.linkerPath : undefined,\n };\n}\n\nfunction buildFullTrace(trace: ExtendedTraceEntry[]): 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(value: Entry, options: DeriveLabelsOptions): EnrichedRecord {\n const { spec, extraTrace } = extractSpecAndTrace(value);\n\n const label = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace);\n const baseTrace = traceStr\n ? (parseJson(traceStr as StringifiedJson<ExtendedTraceEntry[]>) ?? [])\n : [];\n const prefixExtra = extraTrace?.filter((e) => e.position === \"prefix\") ?? [];\n const suffixExtra = extraTrace?.filter((e) => e.position !== \"prefix\") ?? [];\n const trace = [...prefixExtra, ...baseTrace, ...suffixExtra];\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 { fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats(records: EnrichedRecord[]): 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(\n records: EnrichedRecord[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): string[] | undefined {\n const result: string[] = [];\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(\"Unlabeled\");\n continue;\n }\n\n result.push(parts.join(separator));\n }\n\n return result;\n}\n\nfunction countUniqueLabels(result: string[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result).size;\n}\n\nfunction minimizeTypeSet(\n typeSet: Set<string>,\n records: EnrichedRecord[],\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,29 +1,29 @@
|
|
|
1
|
-
import { PObjectSpec } from "@milaboratories/pl-model-common";
|
|
1
|
+
import { PObjectSpec, Trace, Trace as Trace$1, TraceEntry } from "@milaboratories/pl-model-common";
|
|
2
2
|
|
|
3
3
|
//#region src/labels/derive_distinct_labels.d.ts
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
label: string;
|
|
7
|
-
};
|
|
8
|
-
type TraceEntry = {
|
|
9
|
-
id?: string;
|
|
10
|
-
type: string;
|
|
11
|
-
label: string;
|
|
4
|
+
/** SDK-internal trace shape — adds fields used by this algorithm only, not part of the on-disk contract. */
|
|
5
|
+
type ExtendedTraceEntry = Trace[number] & {
|
|
12
6
|
importance?: number;
|
|
7
|
+
position?: "prefix" | "suffix";
|
|
13
8
|
};
|
|
14
|
-
type Trace = TraceEntry[];
|
|
15
9
|
type Entry = PObjectSpec | {
|
|
16
|
-
spec: PObjectSpec;
|
|
17
|
-
|
|
18
|
-
|
|
10
|
+
spec: PObjectSpec; /** Extra trace entries merged with the base trace from annotations. */
|
|
11
|
+
extraTrace?: ExtendedTraceEntry[]; /** Linker steps traversed to discover this column; used to append "via $linkLabel" to derived labels. */
|
|
12
|
+
linkerPath?: {
|
|
13
|
+
spec: PObjectSpec;
|
|
14
|
+
}[];
|
|
19
15
|
};
|
|
20
16
|
type DeriveLabelsOptions = {
|
|
21
17
|
/** Separator to use between label parts (" / " by default) */separator?: string; /** If true, label will be added as suffix (at the end of the generated label). By default label added as a prefix. */
|
|
22
18
|
addLabelAsSuffix?: boolean; /** Force inclusion of native column label */
|
|
23
19
|
includeNativeLabel?: boolean; /** Trace elements list that will be forced to be included in the label. */
|
|
24
20
|
forceTraceElements?: string[];
|
|
21
|
+
/** Custom formatter for linker path suffix. Receives the array of linker labels from the full traversal chain,
|
|
22
|
+
* the column spec, and the column index.
|
|
23
|
+
* If returns undefined, no linker suffix is appended. By default labels are joined with " > " and prefixed with "via ". */
|
|
24
|
+
linkerLabelFormatter?: (linkerLabels: string[], spec: PObjectSpec, index: number) => string | undefined;
|
|
25
25
|
};
|
|
26
|
-
declare function deriveDistinctLabels
|
|
26
|
+
declare function deriveDistinctLabels(values: Entry[], options?: DeriveLabelsOptions): string[];
|
|
27
27
|
//#endregion
|
|
28
|
-
export { DeriveLabelsOptions, Entry, Trace,
|
|
28
|
+
export { DeriveLabelsOptions, Entry, type Trace$1 as Trace, type TraceEntry, deriveDistinctLabels };
|
|
29
29
|
//# sourceMappingURL=derive_distinct_labels.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"derive_distinct_labels.d.ts","names":[],"sources":["../../src/labels/derive_distinct_labels.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"derive_distinct_labels.d.ts","names":[],"sources":["../../src/labels/derive_distinct_labels.ts"],"mappings":";;;;KAkBK,kBAAA,GAAqB,KAAA;EACxB,UAAA;EACA,QAAA;AAAA;AAAA,KAGU,KAAA,GACR,WAAA;EAEE,IAAA,EAAM,WAAA,EANV;EAQI,UAAA,GAAa,kBAAA,IART;EAUJ,UAAA;IAAe,IAAA,EAAM,WAAA;EAAA;AAAA;AAAA,KAGf,mBAAA;EALO,8DAOjB,SAAA,WALoC;EAOpC,gBAAA,YAbE;EAeF,kBAAA,YAbU;EAeV,kBAAA;EAbiB;;;EAiBjB,oBAAA,IACE,YAAA,YACA,IAAA,EAAM,WAAA,EACN,KAAA;AAAA;AAAA,iBAIY,oBAAA,CAAqB,MAAA,EAAQ,KAAA,IAAS,OAAA,GAAS,mBAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Annotation, parseJson, readAnnotation } from "@milaboratories/pl-model-common";
|
|
2
2
|
import { throwError } from "@milaboratories/helpers";
|
|
3
|
+
import { isFunction, isNil as isNil$1 } from "es-toolkit";
|
|
3
4
|
//#region src/labels/derive_distinct_labels.ts
|
|
4
5
|
const DISTANCE_PENALTY = .001;
|
|
5
6
|
const LABEL_TYPE = "__LABEL__";
|
|
@@ -7,13 +8,19 @@ const LABEL_TYPE_FULL = "__LABEL__@1";
|
|
|
7
8
|
function deriveDistinctLabels(values, options = {}) {
|
|
8
9
|
const forceTraceElements = options.forceTraceElements !== void 0 && options.forceTraceElements.length > 0 ? new Set(options.forceTraceElements) : void 0;
|
|
9
10
|
const separator = options.separator ?? " / ";
|
|
11
|
+
const linkerSuffixes = values.map((v, i) => {
|
|
12
|
+
const spec = "spec" in v && typeof v.spec === "object" ? v.spec : v;
|
|
13
|
+
const linkerLabels = extractLinkerLabels(v);
|
|
14
|
+
if (linkerLabels.length === 0) return void 0;
|
|
15
|
+
return isFunction(options.linkerLabelFormatter) ? options.linkerLabelFormatter(linkerLabels, spec, i) : `via ${linkerLabels.join(" > ")}`;
|
|
16
|
+
});
|
|
10
17
|
const records = values.map((v) => enrichRecord(v, options));
|
|
11
18
|
const stats = collectTypeStats(records);
|
|
12
19
|
const { mainTypes, secondaryTypes } = classifyTypes(stats, values.length);
|
|
13
20
|
const build = (typeSet, force) => buildLabels(records, typeSet, forceTraceElements, separator, force);
|
|
14
21
|
if (mainTypes.length === 0) {
|
|
15
22
|
if (secondaryTypes.length !== 0) throw new Error("Non-empty secondary types list while main types list is empty.");
|
|
16
|
-
return build(new Set(LABEL_TYPE_FULL), true);
|
|
23
|
+
return applyLinkerSuffixes(build(new Set(LABEL_TYPE_FULL), true) ?? throwError("Failed to derive labels using native column labels"), linkerSuffixes);
|
|
17
24
|
}
|
|
18
25
|
let includedCount = 0;
|
|
19
26
|
let additionalType = -1;
|
|
@@ -23,25 +30,37 @@ function deriveDistinctLabels(values, options = {}) {
|
|
|
23
30
|
for (let i = 0; i < includedCount; ++i) currentSet.add(mainTypes[i]);
|
|
24
31
|
if (additionalType >= 0) currentSet.add(mainTypes[additionalType]);
|
|
25
32
|
const candidateResult = build(currentSet, false);
|
|
26
|
-
if (candidateResult !== void 0 && countUniqueLabels(candidateResult) === values.length) return build(minimizeTypeSet(currentSet, records, stats, forceTraceElements, options, separator), false) ?? throwError("Failed to derive unique labels");
|
|
33
|
+
if (candidateResult !== void 0 && countUniqueLabels(candidateResult) === values.length) return applyLinkerSuffixes(build(minimizeTypeSet(currentSet, records, stats, forceTraceElements, options, separator), false) ?? throwError("Failed to derive unique labels"), linkerSuffixes);
|
|
27
34
|
additionalType++;
|
|
28
35
|
if (additionalType >= mainTypes.length) {
|
|
29
36
|
includedCount++;
|
|
30
37
|
additionalType = includedCount;
|
|
31
38
|
}
|
|
32
39
|
}
|
|
33
|
-
return build(minimizeTypeSet(new Set([...mainTypes, ...secondaryTypes]), records, stats, forceTraceElements, options, separator), true) ?? throwError("Failed to derive unique labels");
|
|
40
|
+
return applyLinkerSuffixes(build(minimizeTypeSet(new Set([...mainTypes, ...secondaryTypes]), records, stats, forceTraceElements, options, separator), true) ?? throwError("Failed to derive unique labels"), linkerSuffixes);
|
|
41
|
+
}
|
|
42
|
+
/** Apply pre-formatted linker suffixes to labels that have them. */
|
|
43
|
+
function applyLinkerSuffixes(labels, suffixes) {
|
|
44
|
+
return labels.map((label, i) => isNil$1(suffixes[i]) ? label : `${label} ${suffixes[i]}`);
|
|
45
|
+
}
|
|
46
|
+
/** Extract linker labels from every step of the linkers path. */
|
|
47
|
+
function extractLinkerLabels(entry) {
|
|
48
|
+
if (!("spec" in entry) || typeof entry.spec !== "object") return [];
|
|
49
|
+
const path = entry.linkerPath;
|
|
50
|
+
if (path === void 0 || path.length === 0) return [];
|
|
51
|
+
const labels = [];
|
|
52
|
+
for (const step of path) {
|
|
53
|
+
const label = (readAnnotation(step.spec, Annotation.LinkLabel) ?? readAnnotation(step.spec, Annotation.Label))?.trim();
|
|
54
|
+
if (label !== void 0 && label.length > 0) labels.push(label);
|
|
55
|
+
}
|
|
56
|
+
return labels;
|
|
34
57
|
}
|
|
35
58
|
function extractSpecAndTrace(entry) {
|
|
36
|
-
|
|
37
|
-
spec: entry.spec,
|
|
38
|
-
prefixTrace: entry.prefixTrace,
|
|
39
|
-
suffixTrace: entry.suffixTrace
|
|
40
|
-
};
|
|
59
|
+
const isEnriched = "spec" in entry && typeof entry.spec === "object";
|
|
41
60
|
return {
|
|
42
|
-
spec: entry,
|
|
43
|
-
|
|
44
|
-
|
|
61
|
+
spec: isEnriched ? entry.spec : entry,
|
|
62
|
+
extraTrace: isEnriched ? entry.extraTrace : void 0,
|
|
63
|
+
linkerPath: isEnriched ? entry.linkerPath : void 0
|
|
45
64
|
};
|
|
46
65
|
}
|
|
47
66
|
function buildFullTrace(trace) {
|
|
@@ -61,14 +80,16 @@ function buildFullTrace(trace) {
|
|
|
61
80
|
return result;
|
|
62
81
|
}
|
|
63
82
|
function enrichRecord(value, options) {
|
|
64
|
-
const { spec,
|
|
83
|
+
const { spec, extraTrace } = extractSpecAndTrace(value);
|
|
65
84
|
const label = readAnnotation(spec, Annotation.Label);
|
|
66
85
|
const traceStr = readAnnotation(spec, Annotation.Trace);
|
|
67
86
|
const baseTrace = traceStr ? parseJson(traceStr) ?? [] : [];
|
|
87
|
+
const prefixExtra = extraTrace?.filter((e) => e.position === "prefix") ?? [];
|
|
88
|
+
const suffixExtra = extraTrace?.filter((e) => e.position !== "prefix") ?? [];
|
|
68
89
|
const trace = [
|
|
69
|
-
...
|
|
90
|
+
...prefixExtra,
|
|
70
91
|
...baseTrace,
|
|
71
|
-
...
|
|
92
|
+
...suffixExtra
|
|
72
93
|
];
|
|
73
94
|
if (label !== void 0) {
|
|
74
95
|
const labelEntry = {
|
|
@@ -79,10 +100,7 @@ function enrichRecord(value, options) {
|
|
|
79
100
|
if (options.addLabelAsSuffix) trace.push(labelEntry);
|
|
80
101
|
else trace.splice(0, 0, labelEntry);
|
|
81
102
|
}
|
|
82
|
-
return {
|
|
83
|
-
value,
|
|
84
|
-
fullTrace: buildFullTrace(trace)
|
|
85
|
-
};
|
|
103
|
+
return { fullTrace: buildFullTrace(trace) };
|
|
86
104
|
}
|
|
87
105
|
function collectTypeStats(records) {
|
|
88
106
|
const importances = /* @__PURE__ */ new Map();
|
|
@@ -117,22 +135,16 @@ function buildLabels(records, includedTypes, forceTraceElements, separator, forc
|
|
|
117
135
|
for (const ft of r.fullTrace) if (includedTypes.has(ft.fullType) || forceTraceElements?.has(ft.type)) parts.push(ft.label);
|
|
118
136
|
if (parts.length === 0) {
|
|
119
137
|
if (!force) return void 0;
|
|
120
|
-
result.push(
|
|
121
|
-
label: "Unlabeled",
|
|
122
|
-
value: r.value
|
|
123
|
-
});
|
|
138
|
+
result.push("Unlabeled");
|
|
124
139
|
continue;
|
|
125
140
|
}
|
|
126
|
-
result.push(
|
|
127
|
-
label: parts.join(separator),
|
|
128
|
-
value: r.value
|
|
129
|
-
});
|
|
141
|
+
result.push(parts.join(separator));
|
|
130
142
|
}
|
|
131
143
|
return result;
|
|
132
144
|
}
|
|
133
145
|
function countUniqueLabels(result) {
|
|
134
146
|
if (result === void 0) return 0;
|
|
135
|
-
return new Set(result
|
|
147
|
+
return new Set(result).size;
|
|
136
148
|
}
|
|
137
149
|
function minimizeTypeSet(typeSet, records, stats, forceTraceElements, options, separator) {
|
|
138
150
|
const initialResult = buildLabels(records, typeSet, forceTraceElements, separator, false);
|
|
@@ -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":["isNil"],"sources":["../../src/labels/derive_distinct_labels.ts"],"sourcesContent":["import {\n Annotation,\n parseJson,\n readAnnotation,\n type PObjectSpec,\n type StringifiedJson,\n type Trace,\n} from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { isFunction, isNil } from \"es-toolkit\";\n\nexport type { Trace, TraceEntry } from \"@milaboratories/pl-model-common\";\n\nconst DISTANCE_PENALTY = 0.001;\nconst LABEL_TYPE = \"__LABEL__\";\nconst LABEL_TYPE_FULL = \"__LABEL__@1\";\n\n/** SDK-internal trace shape — adds fields used by this algorithm only, not part of the on-disk contract. */\ntype ExtendedTraceEntry = Trace[number] & {\n importance?: number;\n position?: \"prefix\" | \"suffix\";\n};\n\nexport type Entry =\n | PObjectSpec\n | {\n spec: PObjectSpec;\n /** Extra trace entries merged with the base trace from annotations. */\n extraTrace?: ExtendedTraceEntry[];\n /** Linker steps traversed to discover this column; used to append \"via $linkLabel\" to derived labels. */\n linkerPath?: { spec: PObjectSpec }[];\n };\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 /** Custom formatter for linker path suffix. Receives the array of linker labels from the full traversal chain,\n * the column spec, and the column index.\n * If returns undefined, no linker suffix is appended. By default labels are joined with \" > \" and prefixed with \"via \". */\n linkerLabelFormatter?: (\n linkerLabels: string[],\n spec: PObjectSpec,\n index: number,\n ) => string | undefined;\n};\n\nexport function deriveDistinctLabels(values: Entry[], options: DeriveLabelsOptions = {}): string[] {\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 // Collect per-entry linker suffixes before disambiguation\n const linkerSuffixes = values.map((v, i) => {\n const spec = \"spec\" in v && typeof v.spec === \"object\" ? v.spec : (v as PObjectSpec);\n const linkerLabels = extractLinkerLabels(v);\n if (linkerLabels.length === 0) return undefined;\n return isFunction(options.linkerLabelFormatter)\n ? options.linkerLabelFormatter(linkerLabels, spec, i)\n : `via ${linkerLabels.join(\" > \")}`;\n });\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\n return applyLinkerSuffixes(\n build(new Set(LABEL_TYPE_FULL), true) ??\n throwError(\"Failed to derive labels using native column labels\"),\n linkerSuffixes,\n );\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 applyLinkerSuffixes(\n build(minimized, false) ?? throwError(\"Failed to derive unique labels\"),\n linkerSuffixes,\n );\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 applyLinkerSuffixes(\n build(minimized, true) ?? throwError(\"Failed to derive unique labels\"),\n linkerSuffixes,\n );\n}\n\n/** Apply pre-formatted linker suffixes to labels that have them. */\nfunction applyLinkerSuffixes(labels: string[], suffixes: (string | undefined)[]): string[] {\n return labels.map((label, i) => (isNil(suffixes[i]) ? label : `${label} ${suffixes[i]}`));\n}\n\n/** Extract linker labels from every step of the linkers path. */\nfunction extractLinkerLabels(entry: Entry): string[] {\n if (!(\"spec\" in entry) || typeof entry.spec !== \"object\") return [];\n const path = entry.linkerPath;\n if (path === undefined || path.length === 0) return [];\n const labels: string[] = [];\n for (const step of path) {\n const label = (\n readAnnotation(step.spec, Annotation.LinkLabel) ?? readAnnotation(step.spec, Annotation.Label)\n )?.trim();\n if (label !== undefined && label.length > 0) {\n labels.push(label);\n }\n }\n return labels;\n}\n\n// --- Pure helpers ---\ntype FullTraceEntry = ExtendedTraceEntry & { fullType: string; occurrenceIndex: number };\n\ntype EnrichedRecord = {\n fullTrace: FullTraceEntry[];\n};\n\nfunction extractSpecAndTrace(entry: Entry): {\n spec: PObjectSpec;\n extraTrace: ExtendedTraceEntry[] | undefined;\n linkerPath: { spec: PObjectSpec }[] | undefined;\n} {\n const isEnriched = \"spec\" in entry && typeof entry.spec === \"object\";\n return {\n spec: isEnriched ? entry.spec : (entry as PObjectSpec),\n extraTrace: isEnriched ? entry.extraTrace : undefined,\n linkerPath: isEnriched ? entry.linkerPath : undefined,\n };\n}\n\nfunction buildFullTrace(trace: ExtendedTraceEntry[]): 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(value: Entry, options: DeriveLabelsOptions): EnrichedRecord {\n const { spec, extraTrace } = extractSpecAndTrace(value);\n\n const label = readAnnotation(spec, Annotation.Label);\n const traceStr = readAnnotation(spec, Annotation.Trace);\n const baseTrace = traceStr\n ? (parseJson(traceStr as StringifiedJson<ExtendedTraceEntry[]>) ?? [])\n : [];\n const prefixExtra = extraTrace?.filter((e) => e.position === \"prefix\") ?? [];\n const suffixExtra = extraTrace?.filter((e) => e.position !== \"prefix\") ?? [];\n const trace = [...prefixExtra, ...baseTrace, ...suffixExtra];\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 { fullTrace: buildFullTrace(trace) };\n}\n\ntype TypeStats = {\n importances: Map<string, number>;\n countByType: Map<string, number>;\n};\n\nfunction collectTypeStats(records: EnrichedRecord[]): 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(\n records: EnrichedRecord[],\n includedTypes: Set<string>,\n forceTraceElements: Set<string> | undefined,\n separator: string,\n force: boolean,\n): string[] | undefined {\n const result: string[] = [];\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(\"Unlabeled\");\n continue;\n }\n\n result.push(parts.join(separator));\n }\n\n return result;\n}\n\nfunction countUniqueLabels(result: string[] | undefined): number {\n if (result === undefined) return 0;\n return new Set(result).size;\n}\n\nfunction minimizeTypeSet(\n typeSet: Set<string>,\n records: EnrichedRecord[],\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
package/dist/labels/index.d.ts
CHANGED
|
@@ -1,2 +1 @@
|
|
|
1
|
-
import { DeriveLabelsOptions, Entry, Trace,
|
|
2
|
-
import { writeLabelsToSpecs } from "./write_labels_to_specs.js";
|
|
1
|
+
import { DeriveLabelsOptions, Entry, Trace, TraceEntry, deriveDistinctLabels } from "./derive_distinct_labels.js";
|
package/dist/labels/index.js
CHANGED
package/dist/package.cjs
CHANGED