@platforma-sdk/model 1.65.3 → 1.65.6
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 +7 -4
- package/dist/columns/column_collection_builder.cjs.map +1 -1
- package/dist/columns/column_collection_builder.js +7 -4
- package/dist/columns/column_collection_builder.js.map +1 -1
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/package.json +8 -8
- package/src/columns/column_collection_builder.ts +12 -8
|
@@ -132,10 +132,13 @@ var AnchoredColumnCollectionImpl = class {
|
|
|
132
132
|
const col = this.columnsMap.get(origId) ?? (0, _milaboratories_helpers.throwError)(`Column with id ${origId} not found in collection`);
|
|
133
133
|
const associatedId = this.idDeriver.deriveS(col.spec);
|
|
134
134
|
results.push({
|
|
135
|
-
path: hit.path.map((step) =>
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
path: hit.path.map((step) => {
|
|
136
|
+
if (step.type !== "linker") throw new Error(`Unexpected discover-columns step type: ${step.type}`);
|
|
137
|
+
return {
|
|
138
|
+
linker: remapSnapshot(this.idDeriver.deriveS(step.linker.spec), this.columnsMap.get(step.linker.columnId) ?? (0, _milaboratories_helpers.throwError)(`Linker column with id ${step.linker.columnId} not found in collection`)),
|
|
139
|
+
qualifications: step.qualifications
|
|
140
|
+
};
|
|
141
|
+
}),
|
|
139
142
|
column: remapSnapshot(associatedId, col),
|
|
140
143
|
variants: hit.mappingVariants,
|
|
141
144
|
originalId: origId
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column_collection_builder.cjs","names":["TreeNodeAccessor","ArrayColumnProvider","toColumnSnapshotProvider","AnchoredIdDeriver","createColumnSnapshot","convertColumnSelectorToMultiColumnSelector"],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n MultiColumnSelector,\n NativePObjectId,\n PColumnIdAndSpec,\n PColumnSpec,\n PObjectId,\n SUniversalPColumnId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n AnchoredIdDeriver,\n canonicalizeJson,\n deriveNativeId,\n getAxesId,\n isPColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport type { ColumnSelector, RelaxedColumnSelector } from \"./column_selector\";\nimport { convertColumnSelectorToMultiColumnSelector } from \"./column_selector\";\nimport { TreeNodeAccessor } from \"../render/accessor\";\nimport type { ColumnSnapshot } from \"./column_snapshot\";\nimport { createColumnSnapshot } from \"./column_snapshot\";\nimport type { ColumnSnapshotProvider, ColumnSource } from \"./column_snapshot_provider\";\nimport { ArrayColumnProvider, toColumnSnapshotProvider } from \"./column_snapshot_provider\";\n\nimport type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { uniqBy } from \"es-toolkit\";\n\n// --- FindColumnsOptions ---\n\n/** Options for plain collection findColumns. */\nexport interface FindColumnsOptions {\n /** Include columns matching these selectors. If omitted, includes all columns. */\n include?: ColumnSelector;\n /** Exclude columns matching these selectors. */\n exclude?: ColumnSelector;\n}\n\n// --- ColumnCollection ---\n\n/** Plain collection — no axis context, selector-based filtering only. */\nexport interface ColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** Point lookup by provider-native ID. */\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;\n\n /** Find columns matching selectors. Returns flat list of snapshots.\n * No axis compatibility matching, no linker traversal.\n * Never returns undefined — the \"not ready\" state was absorbed by the builder. */\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[];\n}\n\n// --- AnchoredColumnCollection ---\n\n/** Axis-aware column collection with anchored identity derivation. */\nexport interface AnchoredColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** List of anchors used for discovery, with their resolved specs. */\n getAnchors(): Map<string, PColumnIdAndSpec>;\n\n /** Point lookup by anchored ID. */\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;\n\n /** Axis-aware column discovery. */\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[];\n}\n\n/** Controls axis matching behavior for anchored discovery. */\nexport type MatchingMode = \"enrichment\" | \"related\" | \"exact\";\n\n/** Options for anchored collection findColumns. */\nexport interface AnchoredFindColumnsOptions extends FindColumnsOptions {\n /** Controls axis matching behavior. Default: 'enrichment'. */\n mode?: MatchingMode;\n /** Maximum linker hops for cross-domain discovery (0 = direct only, default: 4). */\n maxHops?: number;\n}\n\n/** Result of anchored discovery — column snapshot + routing info. */\nexport interface ColumnMatch {\n /** Column snapshot with anchored SUniversalPColumnId. */\n readonly column: ColumnSnapshot<SUniversalPColumnId>;\n /** Provider-native ID — for lookups back to the source provider. */\n readonly originalId: PObjectId;\n /** Match variants — different paths/qualifications that reach this column. */\n readonly variants: MatchVariant[];\n /** Linker steps traversed to reach this hit; empty for direct matches. */\n readonly path: {\n linker: ColumnSnapshot<SUniversalPColumnId>;\n qualifications: AxisQualification[];\n }[];\n}\n\n/** Qualifications needed for both query (already-integrated) columns and the hit column. */\nexport interface MatchQualifications {\n /** Qualifications for each query (already-integrated) column set. */\n readonly forQueries: AxisQualification[][];\n /** Qualifications for the hit column. */\n readonly forHit: AxisQualification[];\n}\n\n/** A single mapping variant describing how a hit column can be integrated. */\nexport interface MatchVariant {\n /** Full qualifications needed for integration. */\n readonly qualifications: MatchQualifications;\n /** Distinctive (minimal) qualifications needed for integration. */\n readonly distinctiveQualifications: MatchQualifications;\n}\n\n// --- Build options ---\n\nexport interface BuildOptions {\n allowPartialColumnList?: true;\n}\n\nexport type AnchorEntry = PObjectId | PColumnSpec | RelaxedColumnSelector;\n\nexport interface AnchoredBuildOptions extends BuildOptions {\n anchors: Record<string, AnchorEntry>;\n}\n\n// --- ColumnCollectionBuilder ---\n\n/**\n * Mutable builder that accumulates column sources, then produces\n * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).\n *\n * Each output lambda creates its own builder — a constraint of the\n * computable framework where each output tracks its own dependencies.\n */\nexport class ColumnCollectionBuilder {\n private readonly providers: ColumnSnapshotProvider[] = [];\n\n constructor(private readonly specDriver: PFrameSpecDriver) {}\n\n /**\n * Register a column source. Sources added first take precedence for dedup.\n * Does NOT accept undefined — if a source isn't available yet,\n * the caller should return undefined from the output lambda.\n */\n addSource(source: ColumnSource | TreeNodeAccessor): this {\n if (source instanceof TreeNodeAccessor) {\n const columns = source.getPColumns();\n if (columns) this.providers.push(new ArrayColumnProvider(columns));\n } else {\n this.providers.push(toColumnSnapshotProvider(source));\n }\n return this;\n }\n\n addSources(sources: (ColumnSource | TreeNodeAccessor)[]): this {\n for (const source of sources) {\n this.addSource(source);\n }\n return this;\n }\n\n /** Plain collection — selector-based filtering, PObjectId namespace. */\n build(): undefined | ColumnCollection;\n build(options: {\n allowPartialColumnList: true;\n }): ColumnCollection & { readonly columnListComplete: boolean };\n /** Anchored collection — axis-aware discovery, SUniversalPColumnId namespace. */\n build(\n options: AnchoredBuildOptions & { allowPartialColumnList: true },\n ): AnchoredColumnCollection & { readonly columnListComplete: boolean };\n build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;\n build(\n options?: BuildOptions | AnchoredBuildOptions,\n ):\n | undefined\n | ColumnCollection\n | AnchoredColumnCollection\n | (ColumnCollection & { readonly columnListComplete: boolean })\n | (AnchoredColumnCollection & { readonly columnListComplete: boolean }) {\n const allowPartial = options?.allowPartialColumnList === true;\n\n // Check column list completeness\n const allComplete = this.providers.every((p) => p.isColumnListComplete());\n if (!allComplete && !allowPartial) return undefined;\n\n // Collect all columns, dedup by native ID (first source wins)\n const columns = collectColumns(this.providers);\n const hasAnchors = options !== undefined && \"anchors\" in options;\n\n if (hasAnchors) {\n return new AnchoredColumnCollectionImpl(this.specDriver, {\n anchors: options.anchors,\n columns,\n });\n } else {\n return new ColumnCollectionImpl(this.specDriver, {\n columns,\n });\n }\n }\n}\n\n// --- ColumnCollectionImpl ---\n\ninterface ColumnCollectionImplOptions {\n readonly columns: ColumnSnapshot<PObjectId>[];\n}\n\nclass ColumnCollectionImpl implements ColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = new Map(options.columns.map((col) => [col.id, col]));\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId> {\n const col = this.columns.get(id);\n if (col === undefined) return undefined;\n return this.toSnapshot(col);\n }\n\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[] {\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"enrichment\"),\n });\n\n // Map hits back to snapshots\n const results = response.hits\n .map((hit) => this.columns.get(hit.hit.columnId as PObjectId))\n .filter((col): col is ColumnSnapshot<PObjectId> => col !== undefined)\n .map((col) => this.toSnapshot(col));\n\n return results;\n }\n\n private toSnapshot(col: ColumnSnapshot<PObjectId>): ColumnSnapshot<PObjectId> {\n return remapSnapshot(col.id, col);\n }\n}\n\n// --- AnchoredColumnCollectionImpl ---\n\ninterface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOptions {\n readonly anchors: Record<string, AnchorEntry>;\n}\n\nclass AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {\n private readonly anchorsMap: Map<string, PColumnIdAndSpec>;\n private readonly columnsMap: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly uniqAnchorAxes: ColumnAxesWithQualifications[];\n private readonly idToOriginalIdMap: Map<SUniversalPColumnId, PObjectId>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: AnchoredColumnCollectionImplOptions,\n ) {\n // Create spec frame from all collected columns\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n this.columnsMap = new Map(options.columns.map((col) => [col.id, col]));\n this.anchorsMap = resolveAnchorMap(\n options.anchors,\n options.columns,\n this.specDriver.discoverColumns.bind(this.specDriver, this.specFrameEntry.key),\n );\n this.idDeriver = new AnchoredIdDeriver(\n Object.fromEntries(\n Array.from(this.anchorsMap.entries()).map(([k, v]) => [k, v.spec] as const),\n ),\n );\n this.uniqAnchorAxes = uniqBy(\n Array.from(this.anchorsMap.values(), ({ spec }) => ({\n axesSpec: spec.axesSpec,\n qualifications: [],\n })),\n (axis) => canonicalizeJson(getAxesId(axis.axesSpec)) + canonicalizeJson(axis.qualifications),\n );\n this.idToOriginalIdMap = new Map(\n options.columns.map((col) => [this.idDeriver.deriveS(col.spec), col.id] as const),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getAnchors(): Map<string, PColumnIdAndSpec> {\n return this.anchorsMap;\n }\n\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {\n const origId = this.idToOriginalIdMap.get(id);\n if (origId === undefined) return undefined;\n const col = this.columnsMap.get(origId);\n if (col === undefined) return undefined;\n return remapSnapshot(id, col);\n }\n\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[] {\n const mode = options?.mode ?? \"enrichment\";\n const constraints = matchingModeToConstraints(mode);\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n constraints,\n maxHops: options?.maxHops ?? 4,\n axes: this.uniqAnchorAxes,\n });\n\n // Map every WASM discovery hit to a ColumnMatch.\n // The same physical column may appear multiple times when reachable through\n // different linker paths — each hit becomes a separate ColumnMatch so that\n // the caller can expand them into distinct table columns.\n const results: ColumnMatch[] = [];\n for (const hit of response.hits) {\n const origId = hit.hit.columnId as PObjectId;\n const col =\n this.columnsMap.get(origId) ??\n throwError(`Column with id ${origId} not found in collection`);\n const associatedId = this.idDeriver.deriveS(col.spec);\n\n results.push({\n path: hit.path.map((step) => ({\n linker: remapSnapshot(\n this.idDeriver.deriveS(step.linker.spec),\n this.columnsMap.get(step.linker.columnId) ??\n throwError(`Linker column with id ${step.linker.columnId} not found in collection`),\n ),\n qualifications: step.qualifications,\n })),\n column: remapSnapshot(associatedId, col),\n variants: hit.mappingVariants,\n originalId: origId,\n });\n }\n\n return results;\n }\n}\n\n/**\n * Collect all columns from all providers, dedup by NativePObjectId.\n * First source wins.\n */\nfunction collectColumns(providers: ColumnSnapshotProvider[]): ColumnSnapshot<PObjectId>[] {\n const seen = new Set<NativePObjectId>();\n const result: ColumnSnapshot<PObjectId>[] = [];\n\n for (const provider of providers) {\n const columns = provider.getAllColumns();\n for (const col of columns) {\n const nativeId = deriveNativeId(col.spec);\n if (seen.has(nativeId)) continue;\n seen.add(nativeId);\n result.push(col);\n }\n }\n\n return result;\n}\n\n// --- Shared snapshot helpers ---\n\n/** Create a new snapshot with a different ID, preserving data accessors. */\nfunction remapSnapshot<Id extends PObjectId>(\n id: Id,\n col: ColumnSnapshot<PObjectId>,\n): ColumnSnapshot<Id> {\n return createColumnSnapshot(id, col.spec, col.data, col.dataStatus);\n}\n\n/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */\nfunction toMultiColumnSelectors(input: ColumnSelector): MultiColumnSelector[] {\n return convertColumnSelectorToMultiColumnSelector(input);\n}\n\n// --- Anchor resolution ---\n\n/**\n * Resolve each anchor value to a PColumnSpec.\n * - PColumnSpec: used directly\n * - PObjectId (string): looked up in the collected column map\n */\nfunction resolveAnchorMap(\n anchors: Record<string, AnchorEntry>,\n columns: ColumnSnapshot<PObjectId>[],\n discoverColumns: (request: DiscoverColumnsRequest) => DiscoverColumnsResponse,\n): Map<string, PColumnIdAndSpec> {\n const result = new Map<string, PColumnIdAndSpec>();\n const resovedIds = new Set<PObjectId>();\n const getDuplicateError = (key: string) =>\n `Anchor \"${key}\": selector matched a column that was already matched by another anchor; please refine the selector to match a different column`;\n\n for (const [key, anchor] of Object.entries(anchors)) {\n if (typeof anchor === \"string\") {\n const found =\n columns.find((col) => col.id === anchor) ??\n throwError(`Anchor \"${key}\": column with id \"${anchor}\" not found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: found.spec });\n resovedIds.add(found.id);\n } else if (\"kind\" in anchor) {\n if (!isPColumnSpec(anchor)) throwError(`Anchor \"${key}\": invalid PColumnSpec`);\n const nativeId = deriveNativeId(anchor);\n const found =\n columns.find((col) => deriveNativeId(col.spec) === nativeId) ??\n throwError(`Anchor \"${key}\": no column matching spec found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: anchor });\n resovedIds.add(found.id);\n } else {\n const matched = discoverColumns({\n includeColumns: toMultiColumnSelectors(anchor),\n excludeColumns: undefined,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"exact\"),\n });\n if (matched.hits.length === 0) {\n throwError(`Anchor \"${key}\": no columns matched selector`);\n }\n if (matched.hits.length > 1) {\n throwError(\n `Anchor \"${key}\": selector is ambiguous and matched multiple columns; please refine the selector to match exactly one column`,\n );\n }\n if (resovedIds.has(matched.hits[0].hit.columnId as PObjectId)) {\n throwError(getDuplicateError(key));\n }\n\n result.set(key, matched.hits[0].hit);\n resovedIds.add(matched.hits[0].hit.columnId);\n }\n }\n\n if (resovedIds.size === 0) {\n throwError(\"At least one anchor must be resolved to a valid column\");\n }\n\n return result;\n}\n\n// --- MatchingMode → DiscoverColumnsConstraints ---\n\nfunction matchingModeToConstraints(mode: MatchingMode): DiscoverColumnsConstraints {\n switch (mode) {\n case \"enrichment\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: false,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"related\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"exact\":\n return {\n allowFloatingSourceAxes: false,\n allowFloatingHitAxes: false,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"column_collection_builder.cjs","names":["TreeNodeAccessor","ArrayColumnProvider","toColumnSnapshotProvider","AnchoredIdDeriver","createColumnSnapshot","convertColumnSelectorToMultiColumnSelector"],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n MultiColumnSelector,\n NativePObjectId,\n PColumnIdAndSpec,\n PColumnSpec,\n PObjectId,\n SUniversalPColumnId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n AnchoredIdDeriver,\n canonicalizeJson,\n deriveNativeId,\n getAxesId,\n isPColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport type { ColumnSelector, RelaxedColumnSelector } from \"./column_selector\";\nimport { convertColumnSelectorToMultiColumnSelector } from \"./column_selector\";\nimport { TreeNodeAccessor } from \"../render/accessor\";\nimport type { ColumnSnapshot } from \"./column_snapshot\";\nimport { createColumnSnapshot } from \"./column_snapshot\";\nimport type { ColumnSnapshotProvider, ColumnSource } from \"./column_snapshot_provider\";\nimport { ArrayColumnProvider, toColumnSnapshotProvider } from \"./column_snapshot_provider\";\n\nimport type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { uniqBy } from \"es-toolkit\";\n\n// --- FindColumnsOptions ---\n\n/** Options for plain collection findColumns. */\nexport interface FindColumnsOptions {\n /** Include columns matching these selectors. If omitted, includes all columns. */\n include?: ColumnSelector;\n /** Exclude columns matching these selectors. */\n exclude?: ColumnSelector;\n}\n\n// --- ColumnCollection ---\n\n/** Plain collection — no axis context, selector-based filtering only. */\nexport interface ColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** Point lookup by provider-native ID. */\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;\n\n /** Find columns matching selectors. Returns flat list of snapshots.\n * No axis compatibility matching, no linker traversal.\n * Never returns undefined — the \"not ready\" state was absorbed by the builder. */\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[];\n}\n\n// --- AnchoredColumnCollection ---\n\n/** Axis-aware column collection with anchored identity derivation. */\nexport interface AnchoredColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** List of anchors used for discovery, with their resolved specs. */\n getAnchors(): Map<string, PColumnIdAndSpec>;\n\n /** Point lookup by anchored ID. */\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;\n\n /** Axis-aware column discovery. */\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[];\n}\n\n/** Controls axis matching behavior for anchored discovery. */\nexport type MatchingMode = \"enrichment\" | \"related\" | \"exact\";\n\n/** Options for anchored collection findColumns. */\nexport interface AnchoredFindColumnsOptions extends FindColumnsOptions {\n /** Controls axis matching behavior. Default: 'enrichment'. */\n mode?: MatchingMode;\n /** Maximum linker hops for cross-domain discovery (0 = direct only, default: 4). */\n maxHops?: number;\n}\n\n/** Result of anchored discovery — column snapshot + routing info. */\nexport interface ColumnMatch {\n /** Column snapshot with anchored SUniversalPColumnId. */\n readonly column: ColumnSnapshot<SUniversalPColumnId>;\n /** Provider-native ID — for lookups back to the source provider. */\n readonly originalId: PObjectId;\n /** Match variants — different paths/qualifications that reach this column. */\n readonly variants: MatchVariant[];\n /** Linker steps traversed to reach this hit; empty for direct matches. */\n readonly path: {\n linker: ColumnSnapshot<SUniversalPColumnId>;\n qualifications: AxisQualification[];\n }[];\n}\n\n/** Qualifications needed for both query (already-integrated) columns and the hit column. */\nexport interface MatchQualifications {\n /** Qualifications for each query (already-integrated) column set. */\n readonly forQueries: AxisQualification[][];\n /** Qualifications for the hit column. */\n readonly forHit: AxisQualification[];\n}\n\n/** A single mapping variant describing how a hit column can be integrated. */\nexport interface MatchVariant {\n /** Full qualifications needed for integration. */\n readonly qualifications: MatchQualifications;\n /** Distinctive (minimal) qualifications needed for integration. */\n readonly distinctiveQualifications: MatchQualifications;\n}\n\n// --- Build options ---\n\nexport interface BuildOptions {\n allowPartialColumnList?: true;\n}\n\nexport type AnchorEntry = PObjectId | PColumnSpec | RelaxedColumnSelector;\n\nexport interface AnchoredBuildOptions extends BuildOptions {\n anchors: Record<string, AnchorEntry>;\n}\n\n// --- ColumnCollectionBuilder ---\n\n/**\n * Mutable builder that accumulates column sources, then produces\n * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).\n *\n * Each output lambda creates its own builder — a constraint of the\n * computable framework where each output tracks its own dependencies.\n */\nexport class ColumnCollectionBuilder {\n private readonly providers: ColumnSnapshotProvider[] = [];\n\n constructor(private readonly specDriver: PFrameSpecDriver) {}\n\n /**\n * Register a column source. Sources added first take precedence for dedup.\n * Does NOT accept undefined — if a source isn't available yet,\n * the caller should return undefined from the output lambda.\n */\n addSource(source: ColumnSource | TreeNodeAccessor): this {\n if (source instanceof TreeNodeAccessor) {\n const columns = source.getPColumns();\n if (columns) this.providers.push(new ArrayColumnProvider(columns));\n } else {\n this.providers.push(toColumnSnapshotProvider(source));\n }\n return this;\n }\n\n addSources(sources: (ColumnSource | TreeNodeAccessor)[]): this {\n for (const source of sources) {\n this.addSource(source);\n }\n return this;\n }\n\n /** Plain collection — selector-based filtering, PObjectId namespace. */\n build(): undefined | ColumnCollection;\n build(options: {\n allowPartialColumnList: true;\n }): ColumnCollection & { readonly columnListComplete: boolean };\n /** Anchored collection — axis-aware discovery, SUniversalPColumnId namespace. */\n build(\n options: AnchoredBuildOptions & { allowPartialColumnList: true },\n ): AnchoredColumnCollection & { readonly columnListComplete: boolean };\n build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;\n build(\n options?: BuildOptions | AnchoredBuildOptions,\n ):\n | undefined\n | ColumnCollection\n | AnchoredColumnCollection\n | (ColumnCollection & { readonly columnListComplete: boolean })\n | (AnchoredColumnCollection & { readonly columnListComplete: boolean }) {\n const allowPartial = options?.allowPartialColumnList === true;\n\n // Check column list completeness\n const allComplete = this.providers.every((p) => p.isColumnListComplete());\n if (!allComplete && !allowPartial) return undefined;\n\n // Collect all columns, dedup by native ID (first source wins)\n const columns = collectColumns(this.providers);\n const hasAnchors = options !== undefined && \"anchors\" in options;\n\n if (hasAnchors) {\n return new AnchoredColumnCollectionImpl(this.specDriver, {\n anchors: options.anchors,\n columns,\n });\n } else {\n return new ColumnCollectionImpl(this.specDriver, {\n columns,\n });\n }\n }\n}\n\n// --- ColumnCollectionImpl ---\n\ninterface ColumnCollectionImplOptions {\n readonly columns: ColumnSnapshot<PObjectId>[];\n}\n\nclass ColumnCollectionImpl implements ColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = new Map(options.columns.map((col) => [col.id, col]));\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId> {\n const col = this.columns.get(id);\n if (col === undefined) return undefined;\n return this.toSnapshot(col);\n }\n\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[] {\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"enrichment\"),\n });\n\n // Map hits back to snapshots\n const results = response.hits\n .map((hit) => this.columns.get(hit.hit.columnId as PObjectId))\n .filter((col): col is ColumnSnapshot<PObjectId> => col !== undefined)\n .map((col) => this.toSnapshot(col));\n\n return results;\n }\n\n private toSnapshot(col: ColumnSnapshot<PObjectId>): ColumnSnapshot<PObjectId> {\n return remapSnapshot(col.id, col);\n }\n}\n\n// --- AnchoredColumnCollectionImpl ---\n\ninterface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOptions {\n readonly anchors: Record<string, AnchorEntry>;\n}\n\nclass AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {\n private readonly anchorsMap: Map<string, PColumnIdAndSpec>;\n private readonly columnsMap: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly uniqAnchorAxes: ColumnAxesWithQualifications[];\n private readonly idToOriginalIdMap: Map<SUniversalPColumnId, PObjectId>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: AnchoredColumnCollectionImplOptions,\n ) {\n // Create spec frame from all collected columns\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n this.columnsMap = new Map(options.columns.map((col) => [col.id, col]));\n this.anchorsMap = resolveAnchorMap(\n options.anchors,\n options.columns,\n this.specDriver.discoverColumns.bind(this.specDriver, this.specFrameEntry.key),\n );\n this.idDeriver = new AnchoredIdDeriver(\n Object.fromEntries(\n Array.from(this.anchorsMap.entries()).map(([k, v]) => [k, v.spec] as const),\n ),\n );\n this.uniqAnchorAxes = uniqBy(\n Array.from(this.anchorsMap.values(), ({ spec }) => ({\n axesSpec: spec.axesSpec,\n qualifications: [],\n })),\n (axis) => canonicalizeJson(getAxesId(axis.axesSpec)) + canonicalizeJson(axis.qualifications),\n );\n this.idToOriginalIdMap = new Map(\n options.columns.map((col) => [this.idDeriver.deriveS(col.spec), col.id] as const),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getAnchors(): Map<string, PColumnIdAndSpec> {\n return this.anchorsMap;\n }\n\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {\n const origId = this.idToOriginalIdMap.get(id);\n if (origId === undefined) return undefined;\n const col = this.columnsMap.get(origId);\n if (col === undefined) return undefined;\n return remapSnapshot(id, col);\n }\n\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[] {\n const mode = options?.mode ?? \"enrichment\";\n const constraints = matchingModeToConstraints(mode);\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n constraints,\n maxHops: options?.maxHops ?? 4,\n axes: this.uniqAnchorAxes,\n });\n\n // Map every WASM discovery hit to a ColumnMatch.\n // The same physical column may appear multiple times when reachable through\n // different linker paths — each hit becomes a separate ColumnMatch so that\n // the caller can expand them into distinct table columns.\n const results: ColumnMatch[] = [];\n for (const hit of response.hits) {\n const origId = hit.hit.columnId as PObjectId;\n const col =\n this.columnsMap.get(origId) ??\n throwError(`Column with id ${origId} not found in collection`);\n const associatedId = this.idDeriver.deriveS(col.spec);\n\n results.push({\n path: hit.path.map((step) => {\n if (step.type !== \"linker\")\n throw new Error(`Unexpected discover-columns step type: ${step.type}`);\n return {\n linker: remapSnapshot(\n this.idDeriver.deriveS(step.linker.spec),\n this.columnsMap.get(step.linker.columnId) ??\n throwError(`Linker column with id ${step.linker.columnId} not found in collection`),\n ),\n qualifications: step.qualifications,\n };\n }),\n column: remapSnapshot(associatedId, col),\n variants: hit.mappingVariants,\n originalId: origId,\n });\n }\n\n return results;\n }\n}\n\n/**\n * Collect all columns from all providers, dedup by NativePObjectId.\n * First source wins.\n */\nfunction collectColumns(providers: ColumnSnapshotProvider[]): ColumnSnapshot<PObjectId>[] {\n const seen = new Set<NativePObjectId>();\n const result: ColumnSnapshot<PObjectId>[] = [];\n\n for (const provider of providers) {\n const columns = provider.getAllColumns();\n for (const col of columns) {\n const nativeId = deriveNativeId(col.spec);\n if (seen.has(nativeId)) continue;\n seen.add(nativeId);\n result.push(col);\n }\n }\n\n return result;\n}\n\n// --- Shared snapshot helpers ---\n\n/** Create a new snapshot with a different ID, preserving data accessors. */\nfunction remapSnapshot<Id extends PObjectId>(\n id: Id,\n col: ColumnSnapshot<PObjectId>,\n): ColumnSnapshot<Id> {\n return createColumnSnapshot(id, col.spec, col.data, col.dataStatus);\n}\n\n/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */\nfunction toMultiColumnSelectors(input: ColumnSelector): MultiColumnSelector[] {\n return convertColumnSelectorToMultiColumnSelector(input);\n}\n\n// --- Anchor resolution ---\n\n/**\n * Resolve each anchor value to a PColumnSpec.\n * - PColumnSpec: used directly\n * - PObjectId (string): looked up in the collected column map\n */\nfunction resolveAnchorMap(\n anchors: Record<string, AnchorEntry>,\n columns: ColumnSnapshot<PObjectId>[],\n discoverColumns: (request: DiscoverColumnsRequest) => DiscoverColumnsResponse,\n): Map<string, PColumnIdAndSpec> {\n const result = new Map<string, PColumnIdAndSpec>();\n const resovedIds = new Set<PObjectId>();\n const getDuplicateError = (key: string) =>\n `Anchor \"${key}\": selector matched a column that was already matched by another anchor; please refine the selector to match a different column`;\n\n for (const [key, anchor] of Object.entries(anchors)) {\n if (typeof anchor === \"string\") {\n const found =\n columns.find((col) => col.id === anchor) ??\n throwError(`Anchor \"${key}\": column with id \"${anchor}\" not found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: found.spec });\n resovedIds.add(found.id);\n } else if (\"kind\" in anchor) {\n if (!isPColumnSpec(anchor)) throwError(`Anchor \"${key}\": invalid PColumnSpec`);\n const nativeId = deriveNativeId(anchor);\n const found =\n columns.find((col) => deriveNativeId(col.spec) === nativeId) ??\n throwError(`Anchor \"${key}\": no column matching spec found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: anchor });\n resovedIds.add(found.id);\n } else {\n const matched = discoverColumns({\n includeColumns: toMultiColumnSelectors(anchor),\n excludeColumns: undefined,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"exact\"),\n });\n if (matched.hits.length === 0) {\n throwError(`Anchor \"${key}\": no columns matched selector`);\n }\n if (matched.hits.length > 1) {\n throwError(\n `Anchor \"${key}\": selector is ambiguous and matched multiple columns; please refine the selector to match exactly one column`,\n );\n }\n if (resovedIds.has(matched.hits[0].hit.columnId as PObjectId)) {\n throwError(getDuplicateError(key));\n }\n\n result.set(key, matched.hits[0].hit);\n resovedIds.add(matched.hits[0].hit.columnId);\n }\n }\n\n if (resovedIds.size === 0) {\n throwError(\"At least one anchor must be resolved to a valid column\");\n }\n\n return result;\n}\n\n// --- MatchingMode → DiscoverColumnsConstraints ---\n\nfunction matchingModeToConstraints(mode: MatchingMode): DiscoverColumnsConstraints {\n switch (mode) {\n case \"enrichment\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: false,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"related\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"exact\":\n return {\n allowFloatingSourceAxes: false,\n allowFloatingHitAxes: false,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n }\n}\n"],"mappings":"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"}
|
|
@@ -131,10 +131,13 @@ var AnchoredColumnCollectionImpl = class {
|
|
|
131
131
|
const col = this.columnsMap.get(origId) ?? throwError(`Column with id ${origId} not found in collection`);
|
|
132
132
|
const associatedId = this.idDeriver.deriveS(col.spec);
|
|
133
133
|
results.push({
|
|
134
|
-
path: hit.path.map((step) =>
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
134
|
+
path: hit.path.map((step) => {
|
|
135
|
+
if (step.type !== "linker") throw new Error(`Unexpected discover-columns step type: ${step.type}`);
|
|
136
|
+
return {
|
|
137
|
+
linker: remapSnapshot(this.idDeriver.deriveS(step.linker.spec), this.columnsMap.get(step.linker.columnId) ?? throwError(`Linker column with id ${step.linker.columnId} not found in collection`)),
|
|
138
|
+
qualifications: step.qualifications
|
|
139
|
+
};
|
|
140
|
+
}),
|
|
138
141
|
column: remapSnapshot(associatedId, col),
|
|
139
142
|
variants: hit.mappingVariants,
|
|
140
143
|
originalId: origId
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column_collection_builder.js","names":[],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n MultiColumnSelector,\n NativePObjectId,\n PColumnIdAndSpec,\n PColumnSpec,\n PObjectId,\n SUniversalPColumnId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n AnchoredIdDeriver,\n canonicalizeJson,\n deriveNativeId,\n getAxesId,\n isPColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport type { ColumnSelector, RelaxedColumnSelector } from \"./column_selector\";\nimport { convertColumnSelectorToMultiColumnSelector } from \"./column_selector\";\nimport { TreeNodeAccessor } from \"../render/accessor\";\nimport type { ColumnSnapshot } from \"./column_snapshot\";\nimport { createColumnSnapshot } from \"./column_snapshot\";\nimport type { ColumnSnapshotProvider, ColumnSource } from \"./column_snapshot_provider\";\nimport { ArrayColumnProvider, toColumnSnapshotProvider } from \"./column_snapshot_provider\";\n\nimport type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { uniqBy } from \"es-toolkit\";\n\n// --- FindColumnsOptions ---\n\n/** Options for plain collection findColumns. */\nexport interface FindColumnsOptions {\n /** Include columns matching these selectors. If omitted, includes all columns. */\n include?: ColumnSelector;\n /** Exclude columns matching these selectors. */\n exclude?: ColumnSelector;\n}\n\n// --- ColumnCollection ---\n\n/** Plain collection — no axis context, selector-based filtering only. */\nexport interface ColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** Point lookup by provider-native ID. */\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;\n\n /** Find columns matching selectors. Returns flat list of snapshots.\n * No axis compatibility matching, no linker traversal.\n * Never returns undefined — the \"not ready\" state was absorbed by the builder. */\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[];\n}\n\n// --- AnchoredColumnCollection ---\n\n/** Axis-aware column collection with anchored identity derivation. */\nexport interface AnchoredColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** List of anchors used for discovery, with their resolved specs. */\n getAnchors(): Map<string, PColumnIdAndSpec>;\n\n /** Point lookup by anchored ID. */\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;\n\n /** Axis-aware column discovery. */\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[];\n}\n\n/** Controls axis matching behavior for anchored discovery. */\nexport type MatchingMode = \"enrichment\" | \"related\" | \"exact\";\n\n/** Options for anchored collection findColumns. */\nexport interface AnchoredFindColumnsOptions extends FindColumnsOptions {\n /** Controls axis matching behavior. Default: 'enrichment'. */\n mode?: MatchingMode;\n /** Maximum linker hops for cross-domain discovery (0 = direct only, default: 4). */\n maxHops?: number;\n}\n\n/** Result of anchored discovery — column snapshot + routing info. */\nexport interface ColumnMatch {\n /** Column snapshot with anchored SUniversalPColumnId. */\n readonly column: ColumnSnapshot<SUniversalPColumnId>;\n /** Provider-native ID — for lookups back to the source provider. */\n readonly originalId: PObjectId;\n /** Match variants — different paths/qualifications that reach this column. */\n readonly variants: MatchVariant[];\n /** Linker steps traversed to reach this hit; empty for direct matches. */\n readonly path: {\n linker: ColumnSnapshot<SUniversalPColumnId>;\n qualifications: AxisQualification[];\n }[];\n}\n\n/** Qualifications needed for both query (already-integrated) columns and the hit column. */\nexport interface MatchQualifications {\n /** Qualifications for each query (already-integrated) column set. */\n readonly forQueries: AxisQualification[][];\n /** Qualifications for the hit column. */\n readonly forHit: AxisQualification[];\n}\n\n/** A single mapping variant describing how a hit column can be integrated. */\nexport interface MatchVariant {\n /** Full qualifications needed for integration. */\n readonly qualifications: MatchQualifications;\n /** Distinctive (minimal) qualifications needed for integration. */\n readonly distinctiveQualifications: MatchQualifications;\n}\n\n// --- Build options ---\n\nexport interface BuildOptions {\n allowPartialColumnList?: true;\n}\n\nexport type AnchorEntry = PObjectId | PColumnSpec | RelaxedColumnSelector;\n\nexport interface AnchoredBuildOptions extends BuildOptions {\n anchors: Record<string, AnchorEntry>;\n}\n\n// --- ColumnCollectionBuilder ---\n\n/**\n * Mutable builder that accumulates column sources, then produces\n * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).\n *\n * Each output lambda creates its own builder — a constraint of the\n * computable framework where each output tracks its own dependencies.\n */\nexport class ColumnCollectionBuilder {\n private readonly providers: ColumnSnapshotProvider[] = [];\n\n constructor(private readonly specDriver: PFrameSpecDriver) {}\n\n /**\n * Register a column source. Sources added first take precedence for dedup.\n * Does NOT accept undefined — if a source isn't available yet,\n * the caller should return undefined from the output lambda.\n */\n addSource(source: ColumnSource | TreeNodeAccessor): this {\n if (source instanceof TreeNodeAccessor) {\n const columns = source.getPColumns();\n if (columns) this.providers.push(new ArrayColumnProvider(columns));\n } else {\n this.providers.push(toColumnSnapshotProvider(source));\n }\n return this;\n }\n\n addSources(sources: (ColumnSource | TreeNodeAccessor)[]): this {\n for (const source of sources) {\n this.addSource(source);\n }\n return this;\n }\n\n /** Plain collection — selector-based filtering, PObjectId namespace. */\n build(): undefined | ColumnCollection;\n build(options: {\n allowPartialColumnList: true;\n }): ColumnCollection & { readonly columnListComplete: boolean };\n /** Anchored collection — axis-aware discovery, SUniversalPColumnId namespace. */\n build(\n options: AnchoredBuildOptions & { allowPartialColumnList: true },\n ): AnchoredColumnCollection & { readonly columnListComplete: boolean };\n build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;\n build(\n options?: BuildOptions | AnchoredBuildOptions,\n ):\n | undefined\n | ColumnCollection\n | AnchoredColumnCollection\n | (ColumnCollection & { readonly columnListComplete: boolean })\n | (AnchoredColumnCollection & { readonly columnListComplete: boolean }) {\n const allowPartial = options?.allowPartialColumnList === true;\n\n // Check column list completeness\n const allComplete = this.providers.every((p) => p.isColumnListComplete());\n if (!allComplete && !allowPartial) return undefined;\n\n // Collect all columns, dedup by native ID (first source wins)\n const columns = collectColumns(this.providers);\n const hasAnchors = options !== undefined && \"anchors\" in options;\n\n if (hasAnchors) {\n return new AnchoredColumnCollectionImpl(this.specDriver, {\n anchors: options.anchors,\n columns,\n });\n } else {\n return new ColumnCollectionImpl(this.specDriver, {\n columns,\n });\n }\n }\n}\n\n// --- ColumnCollectionImpl ---\n\ninterface ColumnCollectionImplOptions {\n readonly columns: ColumnSnapshot<PObjectId>[];\n}\n\nclass ColumnCollectionImpl implements ColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = new Map(options.columns.map((col) => [col.id, col]));\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId> {\n const col = this.columns.get(id);\n if (col === undefined) return undefined;\n return this.toSnapshot(col);\n }\n\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[] {\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"enrichment\"),\n });\n\n // Map hits back to snapshots\n const results = response.hits\n .map((hit) => this.columns.get(hit.hit.columnId as PObjectId))\n .filter((col): col is ColumnSnapshot<PObjectId> => col !== undefined)\n .map((col) => this.toSnapshot(col));\n\n return results;\n }\n\n private toSnapshot(col: ColumnSnapshot<PObjectId>): ColumnSnapshot<PObjectId> {\n return remapSnapshot(col.id, col);\n }\n}\n\n// --- AnchoredColumnCollectionImpl ---\n\ninterface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOptions {\n readonly anchors: Record<string, AnchorEntry>;\n}\n\nclass AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {\n private readonly anchorsMap: Map<string, PColumnIdAndSpec>;\n private readonly columnsMap: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly uniqAnchorAxes: ColumnAxesWithQualifications[];\n private readonly idToOriginalIdMap: Map<SUniversalPColumnId, PObjectId>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: AnchoredColumnCollectionImplOptions,\n ) {\n // Create spec frame from all collected columns\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n this.columnsMap = new Map(options.columns.map((col) => [col.id, col]));\n this.anchorsMap = resolveAnchorMap(\n options.anchors,\n options.columns,\n this.specDriver.discoverColumns.bind(this.specDriver, this.specFrameEntry.key),\n );\n this.idDeriver = new AnchoredIdDeriver(\n Object.fromEntries(\n Array.from(this.anchorsMap.entries()).map(([k, v]) => [k, v.spec] as const),\n ),\n );\n this.uniqAnchorAxes = uniqBy(\n Array.from(this.anchorsMap.values(), ({ spec }) => ({\n axesSpec: spec.axesSpec,\n qualifications: [],\n })),\n (axis) => canonicalizeJson(getAxesId(axis.axesSpec)) + canonicalizeJson(axis.qualifications),\n );\n this.idToOriginalIdMap = new Map(\n options.columns.map((col) => [this.idDeriver.deriveS(col.spec), col.id] as const),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getAnchors(): Map<string, PColumnIdAndSpec> {\n return this.anchorsMap;\n }\n\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {\n const origId = this.idToOriginalIdMap.get(id);\n if (origId === undefined) return undefined;\n const col = this.columnsMap.get(origId);\n if (col === undefined) return undefined;\n return remapSnapshot(id, col);\n }\n\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[] {\n const mode = options?.mode ?? \"enrichment\";\n const constraints = matchingModeToConstraints(mode);\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n constraints,\n maxHops: options?.maxHops ?? 4,\n axes: this.uniqAnchorAxes,\n });\n\n // Map every WASM discovery hit to a ColumnMatch.\n // The same physical column may appear multiple times when reachable through\n // different linker paths — each hit becomes a separate ColumnMatch so that\n // the caller can expand them into distinct table columns.\n const results: ColumnMatch[] = [];\n for (const hit of response.hits) {\n const origId = hit.hit.columnId as PObjectId;\n const col =\n this.columnsMap.get(origId) ??\n throwError(`Column with id ${origId} not found in collection`);\n const associatedId = this.idDeriver.deriveS(col.spec);\n\n results.push({\n path: hit.path.map((step) => ({\n linker: remapSnapshot(\n this.idDeriver.deriveS(step.linker.spec),\n this.columnsMap.get(step.linker.columnId) ??\n throwError(`Linker column with id ${step.linker.columnId} not found in collection`),\n ),\n qualifications: step.qualifications,\n })),\n column: remapSnapshot(associatedId, col),\n variants: hit.mappingVariants,\n originalId: origId,\n });\n }\n\n return results;\n }\n}\n\n/**\n * Collect all columns from all providers, dedup by NativePObjectId.\n * First source wins.\n */\nfunction collectColumns(providers: ColumnSnapshotProvider[]): ColumnSnapshot<PObjectId>[] {\n const seen = new Set<NativePObjectId>();\n const result: ColumnSnapshot<PObjectId>[] = [];\n\n for (const provider of providers) {\n const columns = provider.getAllColumns();\n for (const col of columns) {\n const nativeId = deriveNativeId(col.spec);\n if (seen.has(nativeId)) continue;\n seen.add(nativeId);\n result.push(col);\n }\n }\n\n return result;\n}\n\n// --- Shared snapshot helpers ---\n\n/** Create a new snapshot with a different ID, preserving data accessors. */\nfunction remapSnapshot<Id extends PObjectId>(\n id: Id,\n col: ColumnSnapshot<PObjectId>,\n): ColumnSnapshot<Id> {\n return createColumnSnapshot(id, col.spec, col.data, col.dataStatus);\n}\n\n/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */\nfunction toMultiColumnSelectors(input: ColumnSelector): MultiColumnSelector[] {\n return convertColumnSelectorToMultiColumnSelector(input);\n}\n\n// --- Anchor resolution ---\n\n/**\n * Resolve each anchor value to a PColumnSpec.\n * - PColumnSpec: used directly\n * - PObjectId (string): looked up in the collected column map\n */\nfunction resolveAnchorMap(\n anchors: Record<string, AnchorEntry>,\n columns: ColumnSnapshot<PObjectId>[],\n discoverColumns: (request: DiscoverColumnsRequest) => DiscoverColumnsResponse,\n): Map<string, PColumnIdAndSpec> {\n const result = new Map<string, PColumnIdAndSpec>();\n const resovedIds = new Set<PObjectId>();\n const getDuplicateError = (key: string) =>\n `Anchor \"${key}\": selector matched a column that was already matched by another anchor; please refine the selector to match a different column`;\n\n for (const [key, anchor] of Object.entries(anchors)) {\n if (typeof anchor === \"string\") {\n const found =\n columns.find((col) => col.id === anchor) ??\n throwError(`Anchor \"${key}\": column with id \"${anchor}\" not found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: found.spec });\n resovedIds.add(found.id);\n } else if (\"kind\" in anchor) {\n if (!isPColumnSpec(anchor)) throwError(`Anchor \"${key}\": invalid PColumnSpec`);\n const nativeId = deriveNativeId(anchor);\n const found =\n columns.find((col) => deriveNativeId(col.spec) === nativeId) ??\n throwError(`Anchor \"${key}\": no column matching spec found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: anchor });\n resovedIds.add(found.id);\n } else {\n const matched = discoverColumns({\n includeColumns: toMultiColumnSelectors(anchor),\n excludeColumns: undefined,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"exact\"),\n });\n if (matched.hits.length === 0) {\n throwError(`Anchor \"${key}\": no columns matched selector`);\n }\n if (matched.hits.length > 1) {\n throwError(\n `Anchor \"${key}\": selector is ambiguous and matched multiple columns; please refine the selector to match exactly one column`,\n );\n }\n if (resovedIds.has(matched.hits[0].hit.columnId as PObjectId)) {\n throwError(getDuplicateError(key));\n }\n\n result.set(key, matched.hits[0].hit);\n resovedIds.add(matched.hits[0].hit.columnId);\n }\n }\n\n if (resovedIds.size === 0) {\n throwError(\"At least one anchor must be resolved to a valid column\");\n }\n\n return result;\n}\n\n// --- MatchingMode → DiscoverColumnsConstraints ---\n\nfunction matchingModeToConstraints(mode: MatchingMode): DiscoverColumnsConstraints {\n switch (mode) {\n case \"enrichment\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: false,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"related\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"exact\":\n return {\n allowFloatingSourceAxes: false,\n allowFloatingHitAxes: false,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"column_collection_builder.js","names":[],"sources":["../../src/columns/column_collection_builder.ts"],"sourcesContent":["import type {\n AxisQualification,\n ColumnAxesWithQualifications,\n DiscoverColumnsConstraints,\n DiscoverColumnsRequest,\n DiscoverColumnsResponse,\n MultiColumnSelector,\n NativePObjectId,\n PColumnIdAndSpec,\n PColumnSpec,\n PObjectId,\n SUniversalPColumnId,\n} from \"@milaboratories/pl-model-common\";\nimport {\n AnchoredIdDeriver,\n canonicalizeJson,\n deriveNativeId,\n getAxesId,\n isPColumnSpec,\n} from \"@milaboratories/pl-model-common\";\nimport type { ColumnSelector, RelaxedColumnSelector } from \"./column_selector\";\nimport { convertColumnSelectorToMultiColumnSelector } from \"./column_selector\";\nimport { TreeNodeAccessor } from \"../render/accessor\";\nimport type { ColumnSnapshot } from \"./column_snapshot\";\nimport { createColumnSnapshot } from \"./column_snapshot\";\nimport type { ColumnSnapshotProvider, ColumnSource } from \"./column_snapshot_provider\";\nimport { ArrayColumnProvider, toColumnSnapshotProvider } from \"./column_snapshot_provider\";\n\nimport type { PFrameSpecDriver, PoolEntry, SpecFrameHandle } from \"@milaboratories/pl-model-common\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport { uniqBy } from \"es-toolkit\";\n\n// --- FindColumnsOptions ---\n\n/** Options for plain collection findColumns. */\nexport interface FindColumnsOptions {\n /** Include columns matching these selectors. If omitted, includes all columns. */\n include?: ColumnSelector;\n /** Exclude columns matching these selectors. */\n exclude?: ColumnSelector;\n}\n\n// --- ColumnCollection ---\n\n/** Plain collection — no axis context, selector-based filtering only. */\nexport interface ColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** Point lookup by provider-native ID. */\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId>;\n\n /** Find columns matching selectors. Returns flat list of snapshots.\n * No axis compatibility matching, no linker traversal.\n * Never returns undefined — the \"not ready\" state was absorbed by the builder. */\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[];\n}\n\n// --- AnchoredColumnCollection ---\n\n/** Axis-aware column collection with anchored identity derivation. */\nexport interface AnchoredColumnCollection extends Disposable {\n /** Release the underlying spec frame WASM resource. */\n dispose(): void;\n\n /** List of anchors used for discovery, with their resolved specs. */\n getAnchors(): Map<string, PColumnIdAndSpec>;\n\n /** Point lookup by anchored ID. */\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId>;\n\n /** Axis-aware column discovery. */\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[];\n}\n\n/** Controls axis matching behavior for anchored discovery. */\nexport type MatchingMode = \"enrichment\" | \"related\" | \"exact\";\n\n/** Options for anchored collection findColumns. */\nexport interface AnchoredFindColumnsOptions extends FindColumnsOptions {\n /** Controls axis matching behavior. Default: 'enrichment'. */\n mode?: MatchingMode;\n /** Maximum linker hops for cross-domain discovery (0 = direct only, default: 4). */\n maxHops?: number;\n}\n\n/** Result of anchored discovery — column snapshot + routing info. */\nexport interface ColumnMatch {\n /** Column snapshot with anchored SUniversalPColumnId. */\n readonly column: ColumnSnapshot<SUniversalPColumnId>;\n /** Provider-native ID — for lookups back to the source provider. */\n readonly originalId: PObjectId;\n /** Match variants — different paths/qualifications that reach this column. */\n readonly variants: MatchVariant[];\n /** Linker steps traversed to reach this hit; empty for direct matches. */\n readonly path: {\n linker: ColumnSnapshot<SUniversalPColumnId>;\n qualifications: AxisQualification[];\n }[];\n}\n\n/** Qualifications needed for both query (already-integrated) columns and the hit column. */\nexport interface MatchQualifications {\n /** Qualifications for each query (already-integrated) column set. */\n readonly forQueries: AxisQualification[][];\n /** Qualifications for the hit column. */\n readonly forHit: AxisQualification[];\n}\n\n/** A single mapping variant describing how a hit column can be integrated. */\nexport interface MatchVariant {\n /** Full qualifications needed for integration. */\n readonly qualifications: MatchQualifications;\n /** Distinctive (minimal) qualifications needed for integration. */\n readonly distinctiveQualifications: MatchQualifications;\n}\n\n// --- Build options ---\n\nexport interface BuildOptions {\n allowPartialColumnList?: true;\n}\n\nexport type AnchorEntry = PObjectId | PColumnSpec | RelaxedColumnSelector;\n\nexport interface AnchoredBuildOptions extends BuildOptions {\n anchors: Record<string, AnchorEntry>;\n}\n\n// --- ColumnCollectionBuilder ---\n\n/**\n * Mutable builder that accumulates column sources, then produces\n * a ColumnCollection (plain) or AnchoredColumnCollection (with anchors).\n *\n * Each output lambda creates its own builder — a constraint of the\n * computable framework where each output tracks its own dependencies.\n */\nexport class ColumnCollectionBuilder {\n private readonly providers: ColumnSnapshotProvider[] = [];\n\n constructor(private readonly specDriver: PFrameSpecDriver) {}\n\n /**\n * Register a column source. Sources added first take precedence for dedup.\n * Does NOT accept undefined — if a source isn't available yet,\n * the caller should return undefined from the output lambda.\n */\n addSource(source: ColumnSource | TreeNodeAccessor): this {\n if (source instanceof TreeNodeAccessor) {\n const columns = source.getPColumns();\n if (columns) this.providers.push(new ArrayColumnProvider(columns));\n } else {\n this.providers.push(toColumnSnapshotProvider(source));\n }\n return this;\n }\n\n addSources(sources: (ColumnSource | TreeNodeAccessor)[]): this {\n for (const source of sources) {\n this.addSource(source);\n }\n return this;\n }\n\n /** Plain collection — selector-based filtering, PObjectId namespace. */\n build(): undefined | ColumnCollection;\n build(options: {\n allowPartialColumnList: true;\n }): ColumnCollection & { readonly columnListComplete: boolean };\n /** Anchored collection — axis-aware discovery, SUniversalPColumnId namespace. */\n build(\n options: AnchoredBuildOptions & { allowPartialColumnList: true },\n ): AnchoredColumnCollection & { readonly columnListComplete: boolean };\n build(options: AnchoredBuildOptions): undefined | AnchoredColumnCollection;\n build(\n options?: BuildOptions | AnchoredBuildOptions,\n ):\n | undefined\n | ColumnCollection\n | AnchoredColumnCollection\n | (ColumnCollection & { readonly columnListComplete: boolean })\n | (AnchoredColumnCollection & { readonly columnListComplete: boolean }) {\n const allowPartial = options?.allowPartialColumnList === true;\n\n // Check column list completeness\n const allComplete = this.providers.every((p) => p.isColumnListComplete());\n if (!allComplete && !allowPartial) return undefined;\n\n // Collect all columns, dedup by native ID (first source wins)\n const columns = collectColumns(this.providers);\n const hasAnchors = options !== undefined && \"anchors\" in options;\n\n if (hasAnchors) {\n return new AnchoredColumnCollectionImpl(this.specDriver, {\n anchors: options.anchors,\n columns,\n });\n } else {\n return new ColumnCollectionImpl(this.specDriver, {\n columns,\n });\n }\n }\n}\n\n// --- ColumnCollectionImpl ---\n\ninterface ColumnCollectionImplOptions {\n readonly columns: ColumnSnapshot<PObjectId>[];\n}\n\nclass ColumnCollectionImpl implements ColumnCollection, Disposable {\n private readonly columns: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: ColumnCollectionImplOptions,\n ) {\n this.columns = new Map(options.columns.map((col) => [col.id, col]));\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getColumn(id: PObjectId): undefined | ColumnSnapshot<PObjectId> {\n const col = this.columns.get(id);\n if (col === undefined) return undefined;\n return this.toSnapshot(col);\n }\n\n findColumns(options?: FindColumnsOptions): ColumnSnapshot<PObjectId>[] {\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"enrichment\"),\n });\n\n // Map hits back to snapshots\n const results = response.hits\n .map((hit) => this.columns.get(hit.hit.columnId as PObjectId))\n .filter((col): col is ColumnSnapshot<PObjectId> => col !== undefined)\n .map((col) => this.toSnapshot(col));\n\n return results;\n }\n\n private toSnapshot(col: ColumnSnapshot<PObjectId>): ColumnSnapshot<PObjectId> {\n return remapSnapshot(col.id, col);\n }\n}\n\n// --- AnchoredColumnCollectionImpl ---\n\ninterface AnchoredColumnCollectionImplOptions extends ColumnCollectionImplOptions {\n readonly anchors: Record<string, AnchorEntry>;\n}\n\nclass AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposable {\n private readonly anchorsMap: Map<string, PColumnIdAndSpec>;\n private readonly columnsMap: Map<PObjectId, ColumnSnapshot<PObjectId>>;\n\n private readonly idDeriver: AnchoredIdDeriver;\n private readonly uniqAnchorAxes: ColumnAxesWithQualifications[];\n private readonly idToOriginalIdMap: Map<SUniversalPColumnId, PObjectId>;\n private readonly specFrameEntry: PoolEntry<SpecFrameHandle>;\n\n constructor(\n private readonly specDriver: PFrameSpecDriver,\n options: AnchoredColumnCollectionImplOptions,\n ) {\n // Create spec frame from all collected columns\n this.specFrameEntry = this.specDriver.createSpecFrame(\n Object.fromEntries(options.columns.map((col) => [col.id, col.spec])),\n );\n this.columnsMap = new Map(options.columns.map((col) => [col.id, col]));\n this.anchorsMap = resolveAnchorMap(\n options.anchors,\n options.columns,\n this.specDriver.discoverColumns.bind(this.specDriver, this.specFrameEntry.key),\n );\n this.idDeriver = new AnchoredIdDeriver(\n Object.fromEntries(\n Array.from(this.anchorsMap.entries()).map(([k, v]) => [k, v.spec] as const),\n ),\n );\n this.uniqAnchorAxes = uniqBy(\n Array.from(this.anchorsMap.values(), ({ spec }) => ({\n axesSpec: spec.axesSpec,\n qualifications: [],\n })),\n (axis) => canonicalizeJson(getAxesId(axis.axesSpec)) + canonicalizeJson(axis.qualifications),\n );\n this.idToOriginalIdMap = new Map(\n options.columns.map((col) => [this.idDeriver.deriveS(col.spec), col.id] as const),\n );\n }\n\n dispose(): void {\n this.specFrameEntry.unref();\n }\n\n [Symbol.dispose](): void {\n this.dispose();\n }\n\n getAnchors(): Map<string, PColumnIdAndSpec> {\n return this.anchorsMap;\n }\n\n getColumn(id: SUniversalPColumnId): undefined | ColumnSnapshot<SUniversalPColumnId> {\n const origId = this.idToOriginalIdMap.get(id);\n if (origId === undefined) return undefined;\n const col = this.columnsMap.get(origId);\n if (col === undefined) return undefined;\n return remapSnapshot(id, col);\n }\n\n findColumns(options?: AnchoredFindColumnsOptions): ColumnMatch[] {\n const mode = options?.mode ?? \"enrichment\";\n const constraints = matchingModeToConstraints(mode);\n const includeColumns = options?.include ? toMultiColumnSelectors(options.include) : undefined;\n const excludeColumns = options?.exclude ? toMultiColumnSelectors(options.exclude) : undefined;\n\n const response = this.specDriver.discoverColumns(this.specFrameEntry.key, {\n includeColumns,\n excludeColumns,\n constraints,\n maxHops: options?.maxHops ?? 4,\n axes: this.uniqAnchorAxes,\n });\n\n // Map every WASM discovery hit to a ColumnMatch.\n // The same physical column may appear multiple times when reachable through\n // different linker paths — each hit becomes a separate ColumnMatch so that\n // the caller can expand them into distinct table columns.\n const results: ColumnMatch[] = [];\n for (const hit of response.hits) {\n const origId = hit.hit.columnId as PObjectId;\n const col =\n this.columnsMap.get(origId) ??\n throwError(`Column with id ${origId} not found in collection`);\n const associatedId = this.idDeriver.deriveS(col.spec);\n\n results.push({\n path: hit.path.map((step) => {\n if (step.type !== \"linker\")\n throw new Error(`Unexpected discover-columns step type: ${step.type}`);\n return {\n linker: remapSnapshot(\n this.idDeriver.deriveS(step.linker.spec),\n this.columnsMap.get(step.linker.columnId) ??\n throwError(`Linker column with id ${step.linker.columnId} not found in collection`),\n ),\n qualifications: step.qualifications,\n };\n }),\n column: remapSnapshot(associatedId, col),\n variants: hit.mappingVariants,\n originalId: origId,\n });\n }\n\n return results;\n }\n}\n\n/**\n * Collect all columns from all providers, dedup by NativePObjectId.\n * First source wins.\n */\nfunction collectColumns(providers: ColumnSnapshotProvider[]): ColumnSnapshot<PObjectId>[] {\n const seen = new Set<NativePObjectId>();\n const result: ColumnSnapshot<PObjectId>[] = [];\n\n for (const provider of providers) {\n const columns = provider.getAllColumns();\n for (const col of columns) {\n const nativeId = deriveNativeId(col.spec);\n if (seen.has(nativeId)) continue;\n seen.add(nativeId);\n result.push(col);\n }\n }\n\n return result;\n}\n\n// --- Shared snapshot helpers ---\n\n/** Create a new snapshot with a different ID, preserving data accessors. */\nfunction remapSnapshot<Id extends PObjectId>(\n id: Id,\n col: ColumnSnapshot<PObjectId>,\n): ColumnSnapshot<Id> {\n return createColumnSnapshot(id, col.spec, col.data, col.dataStatus);\n}\n\n/** Normalize SDK ColumnSelectorInput to MultiColumnSelector[]. */\nfunction toMultiColumnSelectors(input: ColumnSelector): MultiColumnSelector[] {\n return convertColumnSelectorToMultiColumnSelector(input);\n}\n\n// --- Anchor resolution ---\n\n/**\n * Resolve each anchor value to a PColumnSpec.\n * - PColumnSpec: used directly\n * - PObjectId (string): looked up in the collected column map\n */\nfunction resolveAnchorMap(\n anchors: Record<string, AnchorEntry>,\n columns: ColumnSnapshot<PObjectId>[],\n discoverColumns: (request: DiscoverColumnsRequest) => DiscoverColumnsResponse,\n): Map<string, PColumnIdAndSpec> {\n const result = new Map<string, PColumnIdAndSpec>();\n const resovedIds = new Set<PObjectId>();\n const getDuplicateError = (key: string) =>\n `Anchor \"${key}\": selector matched a column that was already matched by another anchor; please refine the selector to match a different column`;\n\n for (const [key, anchor] of Object.entries(anchors)) {\n if (typeof anchor === \"string\") {\n const found =\n columns.find((col) => col.id === anchor) ??\n throwError(`Anchor \"${key}\": column with id \"${anchor}\" not found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: found.spec });\n resovedIds.add(found.id);\n } else if (\"kind\" in anchor) {\n if (!isPColumnSpec(anchor)) throwError(`Anchor \"${key}\": invalid PColumnSpec`);\n const nativeId = deriveNativeId(anchor);\n const found =\n columns.find((col) => deriveNativeId(col.spec) === nativeId) ??\n throwError(`Anchor \"${key}\": no column matching spec found in sources`);\n if (resovedIds.has(found.id)) {\n throwError(getDuplicateError(key));\n }\n result.set(key, { columnId: found.id, spec: anchor });\n resovedIds.add(found.id);\n } else {\n const matched = discoverColumns({\n includeColumns: toMultiColumnSelectors(anchor),\n excludeColumns: undefined,\n axes: [],\n maxHops: 0,\n constraints: matchingModeToConstraints(\"exact\"),\n });\n if (matched.hits.length === 0) {\n throwError(`Anchor \"${key}\": no columns matched selector`);\n }\n if (matched.hits.length > 1) {\n throwError(\n `Anchor \"${key}\": selector is ambiguous and matched multiple columns; please refine the selector to match exactly one column`,\n );\n }\n if (resovedIds.has(matched.hits[0].hit.columnId as PObjectId)) {\n throwError(getDuplicateError(key));\n }\n\n result.set(key, matched.hits[0].hit);\n resovedIds.add(matched.hits[0].hit.columnId);\n }\n }\n\n if (resovedIds.size === 0) {\n throwError(\"At least one anchor must be resolved to a valid column\");\n }\n\n return result;\n}\n\n// --- MatchingMode → DiscoverColumnsConstraints ---\n\nfunction matchingModeToConstraints(mode: MatchingMode): DiscoverColumnsConstraints {\n switch (mode) {\n case \"enrichment\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: false,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"related\":\n return {\n allowFloatingSourceAxes: true,\n allowFloatingHitAxes: true,\n allowSourceQualifications: true,\n allowHitQualifications: true,\n };\n case \"exact\":\n return {\n allowFloatingSourceAxes: false,\n allowFloatingHitAxes: false,\n allowSourceQualifications: false,\n allowHitQualifications: false,\n };\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;AA0IA,IAAa,0BAAb,MAAqC;CACnC,YAAuD,EAAE;CAEzD,YAAY,YAA+C;AAA9B,OAAA,aAAA;;;;;;;CAO7B,UAAU,QAA+C;AACvD,MAAI,kBAAkB,kBAAkB;GACtC,MAAM,UAAU,OAAO,aAAa;AACpC,OAAI,QAAS,MAAK,UAAU,KAAK,IAAI,oBAAoB,QAAQ,CAAC;QAElE,MAAK,UAAU,KAAK,yBAAyB,OAAO,CAAC;AAEvD,SAAO;;CAGT,WAAW,SAAoD;AAC7D,OAAK,MAAM,UAAU,QACnB,MAAK,UAAU,OAAO;AAExB,SAAO;;CAaT,MACE,SAMwE;EACxE,MAAM,eAAe,SAAS,2BAA2B;AAIzD,MAAI,CADgB,KAAK,UAAU,OAAO,MAAM,EAAE,sBAAsB,CAAC,IACrD,CAAC,aAAc,QAAO,KAAA;EAG1C,MAAM,UAAU,eAAe,KAAK,UAAU;AAG9C,MAFmB,YAAY,KAAA,KAAa,aAAa,QAGvD,QAAO,IAAI,6BAA6B,KAAK,YAAY;GACvD,SAAS,QAAQ;GACjB;GACD,CAAC;MAEF,QAAO,IAAI,qBAAqB,KAAK,YAAY,EAC/C,SACD,CAAC;;;AAWR,IAAM,uBAAN,MAAmE;CACjE;CACA;CAEA,YACE,YACA,SACA;AAFiB,OAAA,aAAA;AAGjB,OAAK,UAAU,IAAI,IAAI,QAAQ,QAAQ,KAAK,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;AACnE,OAAK,iBAAiB,KAAK,WAAW,gBACpC,OAAO,YAAY,QAAQ,QAAQ,KAAK,QAAQ,CAAC,IAAI,IAAI,IAAI,KAAK,CAAC,CAAC,CACrE;;CAGH,UAAgB;AACd,OAAK,eAAe,OAAO;;CAG7B,CAAC,OAAO,WAAiB;AACvB,OAAK,SAAS;;CAGhB,UAAU,IAAsD;EAC9D,MAAM,MAAM,KAAK,QAAQ,IAAI,GAAG;AAChC,MAAI,QAAQ,KAAA,EAAW,QAAO,KAAA;AAC9B,SAAO,KAAK,WAAW,IAAI;;CAG7B,YAAY,SAA2D;EACrE,MAAM,iBAAiB,SAAS,UAAU,uBAAuB,QAAQ,QAAQ,GAAG,KAAA;EACpF,MAAM,iBAAiB,SAAS,UAAU,uBAAuB,QAAQ,QAAQ,GAAG,KAAA;AAgBpF,SAdiB,KAAK,WAAW,gBAAgB,KAAK,eAAe,KAAK;GACxE;GACA;GACA,MAAM,EAAE;GACR,SAAS;GACT,aAAa,0BAA0B,aAAa;GACrD,CAAC,CAGuB,KACtB,KAAK,QAAQ,KAAK,QAAQ,IAAI,IAAI,IAAI,SAAsB,CAAC,CAC7D,QAAQ,QAA0C,QAAQ,KAAA,EAAU,CACpE,KAAK,QAAQ,KAAK,WAAW,IAAI,CAAC;;CAKvC,WAAmB,KAA2D;AAC5E,SAAO,cAAc,IAAI,IAAI,IAAI;;;AAUrC,IAAM,+BAAN,MAAmF;CACjF;CACA;CAEA;CACA;CACA;CACA;CAEA,YACE,YACA,SACA;AAFiB,OAAA,aAAA;AAIjB,OAAK,iBAAiB,KAAK,WAAW,gBACpC,OAAO,YAAY,QAAQ,QAAQ,KAAK,QAAQ,CAAC,IAAI,IAAI,IAAI,KAAK,CAAC,CAAC,CACrE;AACD,OAAK,aAAa,IAAI,IAAI,QAAQ,QAAQ,KAAK,QAAQ,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC;AACtE,OAAK,aAAa,iBAChB,QAAQ,SACR,QAAQ,SACR,KAAK,WAAW,gBAAgB,KAAK,KAAK,YAAY,KAAK,eAAe,IAAI,CAC/E;AACD,OAAK,YAAY,IAAI,kBACnB,OAAO,YACL,MAAM,KAAK,KAAK,WAAW,SAAS,CAAC,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC,GAAG,EAAE,KAAK,CAAU,CAC5E,CACF;AACD,OAAK,iBAAiB,OACpB,MAAM,KAAK,KAAK,WAAW,QAAQ,GAAG,EAAE,YAAY;GAClD,UAAU,KAAK;GACf,gBAAgB,EAAE;GACnB,EAAE,GACF,SAAS,iBAAiB,UAAU,KAAK,SAAS,CAAC,GAAG,iBAAiB,KAAK,eAAe,CAC7F;AACD,OAAK,oBAAoB,IAAI,IAC3B,QAAQ,QAAQ,KAAK,QAAQ,CAAC,KAAK,UAAU,QAAQ,IAAI,KAAK,EAAE,IAAI,GAAG,CAAU,CAClF;;CAGH,UAAgB;AACd,OAAK,eAAe,OAAO;;CAG7B,CAAC,OAAO,WAAiB;AACvB,OAAK,SAAS;;CAGhB,aAA4C;AAC1C,SAAO,KAAK;;CAGd,UAAU,IAA0E;EAClF,MAAM,SAAS,KAAK,kBAAkB,IAAI,GAAG;AAC7C,MAAI,WAAW,KAAA,EAAW,QAAO,KAAA;EACjC,MAAM,MAAM,KAAK,WAAW,IAAI,OAAO;AACvC,MAAI,QAAQ,KAAA,EAAW,QAAO,KAAA;AAC9B,SAAO,cAAc,IAAI,IAAI;;CAG/B,YAAY,SAAqD;EAE/D,MAAM,cAAc,0BADP,SAAS,QAAQ,aACqB;EACnD,MAAM,iBAAiB,SAAS,UAAU,uBAAuB,QAAQ,QAAQ,GAAG,KAAA;EACpF,MAAM,iBAAiB,SAAS,UAAU,uBAAuB,QAAQ,QAAQ,GAAG,KAAA;EAEpF,MAAM,WAAW,KAAK,WAAW,gBAAgB,KAAK,eAAe,KAAK;GACxE;GACA;GACA;GACA,SAAS,SAAS,WAAW;GAC7B,MAAM,KAAK;GACZ,CAAC;EAMF,MAAM,UAAyB,EAAE;AACjC,OAAK,MAAM,OAAO,SAAS,MAAM;GAC/B,MAAM,SAAS,IAAI,IAAI;GACvB,MAAM,MACJ,KAAK,WAAW,IAAI,OAAO,IAC3B,WAAW,kBAAkB,OAAO,0BAA0B;GAChE,MAAM,eAAe,KAAK,UAAU,QAAQ,IAAI,KAAK;AAErD,WAAQ,KAAK;IACX,MAAM,IAAI,KAAK,KAAK,SAAS;AAC3B,SAAI,KAAK,SAAS,SAChB,OAAM,IAAI,MAAM,0CAA0C,KAAK,OAAO;AACxE,YAAO;MACL,QAAQ,cACN,KAAK,UAAU,QAAQ,KAAK,OAAO,KAAK,EACxC,KAAK,WAAW,IAAI,KAAK,OAAO,SAAS,IACvC,WAAW,yBAAyB,KAAK,OAAO,SAAS,0BAA0B,CACtF;MACD,gBAAgB,KAAK;MACtB;MACD;IACF,QAAQ,cAAc,cAAc,IAAI;IACxC,UAAU,IAAI;IACd,YAAY;IACb,CAAC;;AAGJ,SAAO;;;;;;;AAQX,SAAS,eAAe,WAAkE;CACxF,MAAM,uBAAO,IAAI,KAAsB;CACvC,MAAM,SAAsC,EAAE;AAE9C,MAAK,MAAM,YAAY,WAAW;EAChC,MAAM,UAAU,SAAS,eAAe;AACxC,OAAK,MAAM,OAAO,SAAS;GACzB,MAAM,WAAW,eAAe,IAAI,KAAK;AACzC,OAAI,KAAK,IAAI,SAAS,CAAE;AACxB,QAAK,IAAI,SAAS;AAClB,UAAO,KAAK,IAAI;;;AAIpB,QAAO;;;AAMT,SAAS,cACP,IACA,KACoB;AACpB,QAAO,qBAAqB,IAAI,IAAI,MAAM,IAAI,MAAM,IAAI,WAAW;;;AAIrE,SAAS,uBAAuB,OAA8C;AAC5E,QAAO,2CAA2C,MAAM;;;;;;;AAU1D,SAAS,iBACP,SACA,SACA,iBAC+B;CAC/B,MAAM,yBAAS,IAAI,KAA+B;CAClD,MAAM,6BAAa,IAAI,KAAgB;CACvC,MAAM,qBAAqB,QACzB,WAAW,IAAI;AAEjB,MAAK,MAAM,CAAC,KAAK,WAAW,OAAO,QAAQ,QAAQ,CACjD,KAAI,OAAO,WAAW,UAAU;EAC9B,MAAM,QACJ,QAAQ,MAAM,QAAQ,IAAI,OAAO,OAAO,IACxC,WAAW,WAAW,IAAI,qBAAqB,OAAO,wBAAwB;AAChF,MAAI,WAAW,IAAI,MAAM,GAAG,CAC1B,YAAW,kBAAkB,IAAI,CAAC;AAEpC,SAAO,IAAI,KAAK;GAAE,UAAU,MAAM;GAAI,MAAM,MAAM;GAAM,CAAC;AACzD,aAAW,IAAI,MAAM,GAAG;YACf,UAAU,QAAQ;AAC3B,MAAI,CAAC,cAAc,OAAO,CAAE,YAAW,WAAW,IAAI,wBAAwB;EAC9E,MAAM,WAAW,eAAe,OAAO;EACvC,MAAM,QACJ,QAAQ,MAAM,QAAQ,eAAe,IAAI,KAAK,KAAK,SAAS,IAC5D,WAAW,WAAW,IAAI,6CAA6C;AACzE,MAAI,WAAW,IAAI,MAAM,GAAG,CAC1B,YAAW,kBAAkB,IAAI,CAAC;AAEpC,SAAO,IAAI,KAAK;GAAE,UAAU,MAAM;GAAI,MAAM;GAAQ,CAAC;AACrD,aAAW,IAAI,MAAM,GAAG;QACnB;EACL,MAAM,UAAU,gBAAgB;GAC9B,gBAAgB,uBAAuB,OAAO;GAC9C,gBAAgB,KAAA;GAChB,MAAM,EAAE;GACR,SAAS;GACT,aAAa,0BAA0B,QAAQ;GAChD,CAAC;AACF,MAAI,QAAQ,KAAK,WAAW,EAC1B,YAAW,WAAW,IAAI,gCAAgC;AAE5D,MAAI,QAAQ,KAAK,SAAS,EACxB,YACE,WAAW,IAAI,+GAChB;AAEH,MAAI,WAAW,IAAI,QAAQ,KAAK,GAAG,IAAI,SAAsB,CAC3D,YAAW,kBAAkB,IAAI,CAAC;AAGpC,SAAO,IAAI,KAAK,QAAQ,KAAK,GAAG,IAAI;AACpC,aAAW,IAAI,QAAQ,KAAK,GAAG,IAAI,SAAS;;AAIhD,KAAI,WAAW,SAAS,EACtB,YAAW,yDAAyD;AAGtE,QAAO;;AAKT,SAAS,0BAA0B,MAAgD;AACjF,SAAQ,MAAR;EACE,KAAK,aACH,QAAO;GACL,yBAAyB;GACzB,sBAAsB;GACtB,2BAA2B;GAC3B,wBAAwB;GACzB;EACH,KAAK,UACH,QAAO;GACL,yBAAyB;GACzB,sBAAsB;GACtB,2BAA2B;GAC3B,wBAAwB;GACzB;EACH,KAAK,QACH,QAAO;GACL,yBAAyB;GACzB,sBAAsB;GACtB,2BAA2B;GAC3B,wBAAwB;GACzB"}
|
package/dist/package.cjs
CHANGED
package/dist/package.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/model",
|
|
3
|
-
"version": "1.65.
|
|
3
|
+
"version": "1.65.6",
|
|
4
4
|
"description": "Platforma.bio SDK / Block Model",
|
|
5
5
|
"files": [
|
|
6
6
|
"./dist/**/*",
|
|
@@ -31,10 +31,10 @@
|
|
|
31
31
|
"utility-types": "^3.11.0",
|
|
32
32
|
"zod": "~3.25.76",
|
|
33
33
|
"@milaboratories/helpers": "1.14.1",
|
|
34
|
-
"@milaboratories/pl-model-common": "1.31.2",
|
|
35
|
-
"@milaboratories/ptabler-expression-js": "1.2.7",
|
|
36
34
|
"@milaboratories/pl-error-like": "1.12.9",
|
|
37
|
-
"@milaboratories/pl-model-middle-layer": "1.
|
|
35
|
+
"@milaboratories/pl-model-middle-layer": "1.17.0",
|
|
36
|
+
"@milaboratories/pl-model-common": "1.32.0",
|
|
37
|
+
"@milaboratories/ptabler-expression-js": "1.2.9"
|
|
38
38
|
},
|
|
39
39
|
"devDependencies": {
|
|
40
40
|
"@vitest/coverage-istanbul": "^4.1.3",
|
|
@@ -42,10 +42,10 @@
|
|
|
42
42
|
"typescript": "~5.9.3",
|
|
43
43
|
"vitest": "^4.1.3",
|
|
44
44
|
"@milaboratories/build-configs": "2.0.0",
|
|
45
|
-
"@milaboratories/pf-driver": "1.3.
|
|
46
|
-
"@milaboratories/pf-spec-driver": "1.2.
|
|
47
|
-
"@milaboratories/ts-
|
|
48
|
-
"@milaboratories/ts-
|
|
45
|
+
"@milaboratories/pf-driver": "1.3.6",
|
|
46
|
+
"@milaboratories/pf-spec-driver": "1.2.6",
|
|
47
|
+
"@milaboratories/ts-builder": "1.3.2",
|
|
48
|
+
"@milaboratories/ts-configs": "1.2.3"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "ts-builder build --target node",
|
|
@@ -357,14 +357,18 @@ class AnchoredColumnCollectionImpl implements AnchoredColumnCollection, Disposab
|
|
|
357
357
|
const associatedId = this.idDeriver.deriveS(col.spec);
|
|
358
358
|
|
|
359
359
|
results.push({
|
|
360
|
-
path: hit.path.map((step) =>
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
360
|
+
path: hit.path.map((step) => {
|
|
361
|
+
if (step.type !== "linker")
|
|
362
|
+
throw new Error(`Unexpected discover-columns step type: ${step.type}`);
|
|
363
|
+
return {
|
|
364
|
+
linker: remapSnapshot(
|
|
365
|
+
this.idDeriver.deriveS(step.linker.spec),
|
|
366
|
+
this.columnsMap.get(step.linker.columnId) ??
|
|
367
|
+
throwError(`Linker column with id ${step.linker.columnId} not found in collection`),
|
|
368
|
+
),
|
|
369
|
+
qualifications: step.qualifications,
|
|
370
|
+
};
|
|
371
|
+
}),
|
|
368
372
|
column: remapSnapshot(associatedId, col),
|
|
369
373
|
variants: hit.mappingVariants,
|
|
370
374
|
originalId: origId,
|