@platforma-sdk/model 1.80.17 → 1.81.1
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.cjs +9 -6
- package/dist/columns/column.cjs.map +1 -1
- package/dist/columns/column.d.ts +5 -5
- package/dist/columns/column.d.ts.map +1 -1
- package/dist/columns/column.js +10 -7
- package/dist/columns/column.js.map +1 -1
- package/dist/columns/column_providers/index.cjs.map +1 -1
- package/dist/columns/column_providers/index.d.ts.map +1 -1
- package/dist/columns/column_providers/index.js.map +1 -1
- package/dist/columns/column_providers/providers.cjs +5 -5
- package/dist/columns/column_providers/providers.cjs.map +1 -1
- package/dist/columns/column_providers/providers.d.ts +8 -8
- package/dist/columns/column_providers/providers.d.ts.map +1 -1
- package/dist/columns/column_providers/providers.js +5 -5
- package/dist/columns/column_providers/providers.js.map +1 -1
- package/dist/columns/column_providers/types.d.ts +3 -3
- package/dist/columns/column_providers/types.d.ts.map +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.cjs +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.cjs.map +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.d.ts +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.js +1 -1
- package/dist/columns/column_recipes/column_discovered_recipe.js.map +1 -1
- package/dist/columns/column_recipes/column_overrided_recipe.cjs +47 -2
- package/dist/columns/column_recipes/column_overrided_recipe.cjs.map +1 -1
- package/dist/columns/column_recipes/column_overrided_recipe.d.ts +30 -3
- package/dist/columns/column_recipes/column_overrided_recipe.d.ts.map +1 -1
- package/dist/columns/column_recipes/column_overrided_recipe.js +47 -3
- package/dist/columns/column_recipes/column_overrided_recipe.js.map +1 -1
- package/dist/columns/column_recipes/index.cjs +4 -14
- package/dist/columns/column_recipes/index.cjs.map +1 -1
- package/dist/columns/column_recipes/index.d.ts +3 -10
- package/dist/columns/column_recipes/index.d.ts.map +1 -1
- package/dist/columns/column_recipes/index.js +5 -14
- package/dist/columns/column_recipes/index.js.map +1 -1
- package/dist/columns/{column_lazy.cjs → data_column.cjs} +57 -54
- package/dist/columns/data_column.cjs.map +1 -0
- package/dist/columns/data_column.d.ts +152 -0
- package/dist/columns/data_column.d.ts.map +1 -0
- package/dist/columns/{column_lazy.js → data_column.js} +55 -52
- package/dist/columns/data_column.js.map +1 -0
- package/dist/columns/derive_axis_values_labels.cjs +4 -4
- package/dist/columns/derive_axis_values_labels.cjs.map +1 -1
- package/dist/columns/derive_axis_values_labels.d.ts +2 -2
- package/dist/columns/derive_axis_values_labels.js +4 -4
- package/dist/columns/derive_axis_values_labels.js.map +1 -1
- package/dist/columns/index.cjs +9 -9
- package/dist/columns/index.d.ts +5 -5
- package/dist/columns/index.js +5 -5
- package/dist/columns/{expand_by_partition.cjs → split_by_axes.cjs} +13 -8
- package/dist/columns/split_by_axes.cjs.map +1 -0
- package/dist/columns/{expand_by_partition.d.ts → split_by_axes.d.ts} +18 -8
- package/dist/columns/split_by_axes.d.ts.map +1 -0
- package/dist/columns/{expand_by_partition.js → split_by_axes.js} +14 -9
- package/dist/columns/split_by_axes.js.map +1 -0
- package/dist/columns/utils.cjs +50 -43
- package/dist/columns/utils.cjs.map +1 -1
- package/dist/columns/utils.d.ts +44 -19
- package/dist/columns/utils.d.ts.map +1 -1
- package/dist/columns/utils.js +50 -44
- package/dist/columns/utils.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs +3 -3
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js +3 -3
- package/dist/components/PlDataTable/createPlDataTable/createPTableDefV2.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs +2 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js +2 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV2.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js +2 -2
- package/dist/components/PlDataTable/createPlDataTable/createPlDataTableV3.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs +1 -1
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js +2 -2
- package/dist/components/PlDataTable/createPlDataTable/discoverColumns.js.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.cjs.map +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.js +1 -1
- package/dist/components/PlDataTable/createPlDataTable/utils.js.map +1 -1
- package/dist/components/PlDatasetSelector/enrichment_discovery.cjs +1 -1
- package/dist/components/PlDatasetSelector/enrichment_discovery.cjs.map +1 -1
- package/dist/components/PlDatasetSelector/enrichment_discovery.js +2 -2
- package/dist/components/PlDatasetSelector/enrichment_discovery.js.map +1 -1
- package/dist/index.cjs +9 -9
- package/dist/index.d.ts +5 -5
- package/dist/index.js +5 -5
- package/dist/package.cjs +1 -1
- package/dist/package.js +1 -1
- package/package.json +8 -8
- package/src/columns/__test_helpers__/collection_driver.ts +6 -6
- package/src/columns/__test_helpers__/stub_registry.ts +4 -6
- package/src/columns/column.ts +20 -9
- package/src/columns/column_providers/index.ts +9 -3
- package/src/columns/column_providers/providers.ts +16 -15
- package/src/columns/column_providers/types.ts +3 -3
- package/src/columns/column_recipes/column_discovered_recipe.ts +1 -1
- package/src/columns/column_recipes/column_overrided_recipe.ts +58 -4
- package/src/columns/column_recipes/column_recipes.test.ts +2 -2
- package/src/columns/column_recipes/index.ts +5 -20
- package/src/columns/{column_lazy.test.ts → data_column.test.ts} +19 -19
- package/src/columns/{column_lazy.ts → data_column.ts} +105 -67
- package/src/columns/derive_axis_values_labels.ts +4 -4
- package/src/columns/index.ts +2 -2
- package/src/columns/predicates.test.ts +124 -0
- package/src/columns/{expand_by_partition.test.ts → split_by_axes.test.ts} +29 -21
- package/src/columns/{expand_by_partition.ts → split_by_axes.ts} +22 -9
- package/src/columns/utils.ts +53 -48
- package/src/components/PlDataTable/columnResolver.test.ts +3 -3
- package/src/components/PlDataTable/createPlDataTable/createPTableDefV2.ts +3 -3
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV2.ts +2 -2
- package/src/components/PlDataTable/createPlDataTable/createPlDataTableV3.ts +2 -2
- package/src/components/PlDataTable/createPlDataTable/discoverColumns.ts +2 -2
- package/src/components/PlDataTable/createPlDataTable/utils.test.ts +34 -3
- package/src/components/PlDataTable/createPlDataTable/utils.ts +4 -1
- package/src/components/PlDatasetSelector/enrichment_discovery.ts +2 -2
- package/dist/columns/column_lazy.cjs.map +0 -1
- package/dist/columns/column_lazy.d.ts +0 -137
- package/dist/columns/column_lazy.d.ts.map +0 -1
- package/dist/columns/column_lazy.js.map +0 -1
- package/dist/columns/expand_by_partition.cjs.map +0 -1
- package/dist/columns/expand_by_partition.d.ts.map +0 -1
- package/dist/columns/expand_by_partition.js.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column_discovered_recipe.js","names":[],"sources":["../../../src/columns/column_recipes/column_discovered_recipe.ts"],"sourcesContent":["import {\n distillColumnDiscoveredKey,\n extractPObjectId,\n stringifyColumnDiscoveredId,\n type AxisQualification,\n type ColumnDiscoveredId,\n type ColumnDiscoveredKey,\n type ColumnUniversalId,\n type PColumnSpec,\n type PObjectId,\n type SpecOverrides,\n type SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport type { GlobalCfgRenderCtx } from \"../../render/internal\";\nimport type { ColumnFieldStatus, ColumnResolutionStatus } from \"./types\";\nimport { ColumnRecipe } from \"./index\";\nimport { ColumnOverriddenRecipe } from \"./column_overrided_recipe\";\nimport { Column } from \"../column\";\nimport { rebrandLeafId } from \"./leaf_rebrand\";\nimport { throwError } from \"@milaboratories/helpers\";\n\n/**\n * Recipe for columns identified by a {@link ColumnDiscoveredKey}: a base\n * column + a `path` of linkers + qualifications.\n *\n * Specifics:\n * - References more than one column (`column` + each `path[i].column`);\n * {@link getDataStatus} aggregates across the whole set.\n * - {@link getQuery} assembles the {@link SpecQuery} locally\n * ({@link buildSpecQuery}) — the hit is inlined as its own recipe's query\n * tree, linkers fold inside-out into nested `linkerJoin` nodes.\n * - {@link getSpec} passes through to the hit column's own spec: the linker\n * chain only enables co-indexing and does not remap the hit's `axesSpec`, so\n * no engine round-trip is needed (mirrors the Discovered branch of\n * `reconstructSpecFromId` on the host side).\n */\nexport class ColumnDiscoveredRecipe implements ColumnRecipe<ColumnDiscoveredId> {\n /**\n * Validate the key + resolve every referenced column via\n * {@link ColumnLazy.fromId} (which itself checks the leaf accessor reports\n * `hasData()`). Returns `undefined` if the key is malformed or any\n * referenced column is not yet spec-resolvable.\n *\n * Spec JSON is deserialized lazily on first {@link getSpec}/{@link getQuery}.\n */\n static fromKey(\n key: ColumnDiscoveredKey,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n ): undefined | ColumnDiscoveredRecipe {\n const distilled = distillColumnDiscoveredKey(key);\n const columns: Record<ColumnUniversalId, Column> = {};\n for (const uniId of referencedUniIdsOf(distilled)) {\n const recipe = Column(uniId, opts);\n if (recipe === undefined) return undefined;\n columns[uniId] = recipe;\n }\n return new ColumnDiscoveredRecipe(distilled, columns);\n }\n\n /**\n * Static counterpart to {@link fromKey}: returns the resolution status of\n * a {@link ColumnDiscoveredKey} without constructing the recipe. Worst-wins\n * across every referenced {@link ColumnUniversalId} (hit + path linkers),\n * each resolved via the top-level {@link ColumnRecipe.getStatus} dispatcher.\n */\n static getStatusByKey(\n key: ColumnDiscoveredKey,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n ): ColumnResolutionStatus {\n const distilled = distillColumnDiscoveredKey(key);\n let worst: ColumnResolutionStatus = \"present\";\n for (const uniId of referencedUniIdsOf(distilled)) {\n const s = ColumnRecipe.getStatus(uniId, opts);\n if (s === \"absent\") return \"absent\";\n if (s === \"resolving\") worst = \"resolving\";\n }\n return worst;\n }\n\n readonly id: ColumnDiscoveredId;\n private specCache?: { readonly value: PColumnSpec };\n private queryCache?: { readonly value: SpecQuery };\n private dataStatusCache?: { readonly value: ColumnFieldStatus };\n\n private constructor(\n private readonly key: ColumnDiscoveredKey,\n private readonly columns: Record<ColumnUniversalId, ColumnRecipe>,\n ) {\n this.id = stringifyColumnDiscoveredId(this.key);\n }\n\n /**\n * Universal id of the hit column (excluding path/qualifications on top).\n * May itself be a wrapped id (Overridden / Filtered / nested Discovered) —\n * preserves projections applied to the underlying column.\n */\n getHitId(): ColumnUniversalId {\n return this.key.column;\n }\n\n /**\n * Axis qualifications attached to the hit column itself — applied to the\n * outer-join entry that wraps this column at the consumer boundary.\n */\n getColumnQualifications(): readonly AxisQualification[] {\n return this.key.columnQualifications ?? [];\n }\n\n /**\n * Per-primary-column qualifications applied to the primary anchors on\n * this group's side. Keyed by the external primary column id.\n */\n getQueriesQualifications(): Readonly<Record<PObjectId, AxisQualification[]>> {\n return this.key.queriesQualifications ?? {};\n }\n\n /**\n * Leaf {@link PObjectId}s the recipe physically depends on: hit column +\n * each linker in `path`, with any projection wrappers unwrapped down to\n * their underlying storage column. Used to track real-data dependencies\n * (e.g. {@link getDataStatus}), not projected identities.\n */\n getReferencedIds(): PObjectId[] {\n return [...new Set([...referencedUniIdsOf(this.key)].map((uniId) => extractPObjectId(uniId)))];\n }\n\n /**\n * Final spec of a discovered hit is just the hit column's own spec: the\n * linker chain only enables co-indexing, it does not remap the hit's\n * `axesSpec`, and axis qualifications live on the outer join entry (see\n * {@link buildSpecQuery}), not in the spec. So pass through to the hit\n * recipe's `getSpec()` — no engine round-trip needed. This mirrors the\n * Discovered branch of `reconstructSpecFromId` on the host side.\n */\n getSpec(): PColumnSpec {\n if (this.specCache === undefined) {\n const hit =\n this.columns[this.key.column] ??\n throwError(`ColumnDiscoveredRecipe.getSpec: missing column ${this.key.column}`);\n this.specCache = { value: hit.getSpec() };\n }\n return this.specCache.value;\n }\n\n /** IR for building the final spec — see {@link buildSpecQuery}. */\n getQuery(): SpecQuery {\n if (this.queryCache === undefined) {\n this.queryCache = { value: this.buildSpecQuery() };\n }\n return this.queryCache.value;\n }\n\n getDataStatus(): ColumnFieldStatus {\n if (this.dataStatusCache === undefined) {\n this.dataStatusCache = {\n value: Object.values(this.columns).reduce<ColumnFieldStatus>((worst, lazy) => {\n const s = lazy.getDataStatus();\n if (s === \"absent\" || worst === \"absent\") return \"absent\";\n if (s === \"resolving\") return \"resolving\";\n return worst;\n }, \"present\"),\n };\n }\n return this.dataStatusCache.value;\n }\n\n /**\n * Discovered + overrides → Overridden<Discovered>. Delegates to the\n * flat-merge factory of ColumnOverriddenRecipe; subsequent `withSpecs`\n * calls merge at the Overridden level (one wrapper, no nesting).\n */\n withSpecs(overrides: SpecOverrides): ColumnRecipe {\n return ColumnOverriddenRecipe.wrap(this, overrides);\n }\n\n /**\n * Assembles the SpecQuery for this discovered hit by folding `key.path`\n * around the hit column.\n *\n * The hit (innermost) is built by inlining `columns[key.column].getQuery()`\n * — recursing into the hit's own recipe — so wrapping layers on the hit\n * (Overridden / Filtered / nested Discovered) appear in the produced tree.\n * The previous `pframeSpec.buildQuery` path was a flat\n * {@link PObjectId}-only call and could not express that.\n *\n * Linkers stay as plain column references on the linker side of\n * `linkerJoin` (the spec node has no slot for a query-side linker); the\n * linker's recipe id is used directly. The frame registered in\n * {@link getSpec} carries each recipe's final spec under that same id, so\n * the engine resolves linker axes from the post-projection spec.\n *\n * Path ordering matches {@link ColumnDiscoveredKey.path}: `path[0]` is\n * outermost, `path[N-1]` is closest to the hit. We fold from the inside\n * out — innermost wrap first — so the result lines up with that convention.\n *\n * `columnQualifications` / `queriesQualifications` are not emitted here —\n * qualifications live on a {@link SpecQueryJoinEntry} wrapper (lost on\n * unwrapping to {@link SpecQuery}). External consumers apply them at the\n * outer join via {@link getColumnQualifications} / {@link getQueriesQualifications}.\n */\n private buildSpecQuery(): SpecQuery {\n // Preserve the inner hit recipe's full query tree — it may carry\n // wrappers (specOverride / sliceAxes / nested linkerJoin) that the\n // host needs to apply correctly. We only rebrand the terminal column\n // leaf to this.id so two variants of the same physical hit reached via\n // different linker chains stay distinct columns in the engine output.\n const hitRecipe =\n this.columns[this.key.column] ??\n throwError(`ColumnDiscoveredRecipe.buildSpecQuery: missing column ${this.key.column}`);\n let query: SpecQuery = rebrandLeafId(hitRecipe.getQuery(), hitRecipe.id, this.id);\n const path = this.key.path ?? [];\n\n for (let i = path.length - 1; i >= 0; i--) {\n const linker =\n this.columns[path[i].column] ??\n throwError(\n `ColumnDiscoveredRecipe.buildSpecQuery: missing linker column ${path[i].column}`,\n );\n query = {\n type: \"linkerJoin\",\n linker: linker.getQuery(),\n secondary: [{ entry: query }],\n };\n }\n return query;\n }\n}\n\nfunction referencedUniIdsOf(key: ColumnDiscoveredKey): Set<ColumnUniversalId> {\n return new Set<ColumnUniversalId>([key.column, ...(key.path ?? []).map((item) => item.column)]);\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"column_discovered_recipe.js","names":[],"sources":["../../../src/columns/column_recipes/column_discovered_recipe.ts"],"sourcesContent":["import {\n distillColumnDiscoveredKey,\n extractPObjectId,\n stringifyColumnDiscoveredId,\n type AxisQualification,\n type ColumnDiscoveredId,\n type ColumnDiscoveredKey,\n type ColumnUniversalId,\n type PColumnSpec,\n type PObjectId,\n type SpecOverrides,\n type SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport type { GlobalCfgRenderCtx } from \"../../render/internal\";\nimport type { ColumnFieldStatus, ColumnResolutionStatus } from \"./types\";\nimport { ColumnRecipe } from \"./index\";\nimport { ColumnOverriddenRecipe } from \"./column_overrided_recipe\";\nimport { Column } from \"../column\";\nimport { rebrandLeafId } from \"./leaf_rebrand\";\nimport { throwError } from \"@milaboratories/helpers\";\n\n/**\n * Recipe for columns identified by a {@link ColumnDiscoveredKey}: a base\n * column + a `path` of linkers + qualifications.\n *\n * Specifics:\n * - References more than one column (`column` + each `path[i].column`);\n * {@link getDataStatus} aggregates across the whole set.\n * - {@link getQuery} assembles the {@link SpecQuery} locally\n * ({@link buildSpecQuery}) — the hit is inlined as its own recipe's query\n * tree, linkers fold inside-out into nested `linkerJoin` nodes.\n * - {@link getSpec} passes through to the hit column's own spec: the linker\n * chain only enables co-indexing and does not remap the hit's `axesSpec`, so\n * no engine round-trip is needed (mirrors the Discovered branch of\n * `reconstructSpecFromId` on the host side).\n */\nexport class ColumnDiscoveredRecipe implements ColumnRecipe<ColumnDiscoveredId> {\n /**\n * Validate the key + resolve every referenced column via\n * {@link DataColumnRecipe.fromId} (which itself checks the leaf accessor reports\n * `hasData()`). Returns `undefined` if the key is malformed or any\n * referenced column is not yet spec-resolvable.\n *\n * Spec JSON is deserialized lazily on first {@link getSpec}/{@link getQuery}.\n */\n static fromKey(\n key: ColumnDiscoveredKey,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n ): undefined | ColumnDiscoveredRecipe {\n const distilled = distillColumnDiscoveredKey(key);\n const columns: Record<ColumnUniversalId, Column> = {};\n for (const uniId of referencedUniIdsOf(distilled)) {\n const recipe = Column(uniId, opts);\n if (recipe === undefined) return undefined;\n columns[uniId] = recipe;\n }\n return new ColumnDiscoveredRecipe(distilled, columns);\n }\n\n /**\n * Static counterpart to {@link fromKey}: returns the resolution status of\n * a {@link ColumnDiscoveredKey} without constructing the recipe. Worst-wins\n * across every referenced {@link ColumnUniversalId} (hit + path linkers),\n * each resolved via the top-level {@link ColumnRecipe.getStatus} dispatcher.\n */\n static getStatusByKey(\n key: ColumnDiscoveredKey,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n ): ColumnResolutionStatus {\n const distilled = distillColumnDiscoveredKey(key);\n let worst: ColumnResolutionStatus = \"present\";\n for (const uniId of referencedUniIdsOf(distilled)) {\n const s = ColumnRecipe.getStatus(uniId, opts);\n if (s === \"absent\") return \"absent\";\n if (s === \"resolving\") worst = \"resolving\";\n }\n return worst;\n }\n\n readonly id: ColumnDiscoveredId;\n private specCache?: { readonly value: PColumnSpec };\n private queryCache?: { readonly value: SpecQuery };\n private dataStatusCache?: { readonly value: ColumnFieldStatus };\n\n private constructor(\n private readonly key: ColumnDiscoveredKey,\n private readonly columns: Record<ColumnUniversalId, ColumnRecipe>,\n ) {\n this.id = stringifyColumnDiscoveredId(this.key);\n }\n\n /**\n * Universal id of the hit column (excluding path/qualifications on top).\n * May itself be a wrapped id (Overridden / Filtered / nested Discovered) —\n * preserves projections applied to the underlying column.\n */\n getHitId(): ColumnUniversalId {\n return this.key.column;\n }\n\n /**\n * Axis qualifications attached to the hit column itself — applied to the\n * outer-join entry that wraps this column at the consumer boundary.\n */\n getColumnQualifications(): readonly AxisQualification[] {\n return this.key.columnQualifications ?? [];\n }\n\n /**\n * Per-primary-column qualifications applied to the primary anchors on\n * this group's side. Keyed by the external primary column id.\n */\n getQueriesQualifications(): Readonly<Record<PObjectId, AxisQualification[]>> {\n return this.key.queriesQualifications ?? {};\n }\n\n /**\n * Leaf {@link PObjectId}s the recipe physically depends on: hit column +\n * each linker in `path`, with any projection wrappers unwrapped down to\n * their underlying storage column. Used to track real-data dependencies\n * (e.g. {@link getDataStatus}), not projected identities.\n */\n getReferencedIds(): PObjectId[] {\n return [...new Set([...referencedUniIdsOf(this.key)].map((uniId) => extractPObjectId(uniId)))];\n }\n\n /**\n * Final spec of a discovered hit is just the hit column's own spec: the\n * linker chain only enables co-indexing, it does not remap the hit's\n * `axesSpec`, and axis qualifications live on the outer join entry (see\n * {@link buildSpecQuery}), not in the spec. So pass through to the hit\n * recipe's `getSpec()` — no engine round-trip needed. This mirrors the\n * Discovered branch of `reconstructSpecFromId` on the host side.\n */\n getSpec(): PColumnSpec {\n if (this.specCache === undefined) {\n const hit =\n this.columns[this.key.column] ??\n throwError(`ColumnDiscoveredRecipe.getSpec: missing column ${this.key.column}`);\n this.specCache = { value: hit.getSpec() };\n }\n return this.specCache.value;\n }\n\n /** IR for building the final spec — see {@link buildSpecQuery}. */\n getQuery(): SpecQuery {\n if (this.queryCache === undefined) {\n this.queryCache = { value: this.buildSpecQuery() };\n }\n return this.queryCache.value;\n }\n\n getDataStatus(): ColumnFieldStatus {\n if (this.dataStatusCache === undefined) {\n this.dataStatusCache = {\n value: Object.values(this.columns).reduce<ColumnFieldStatus>((worst, lazy) => {\n const s = lazy.getDataStatus();\n if (s === \"absent\" || worst === \"absent\") return \"absent\";\n if (s === \"resolving\") return \"resolving\";\n return worst;\n }, \"present\"),\n };\n }\n return this.dataStatusCache.value;\n }\n\n /**\n * Discovered + overrides → Overridden<Discovered>. Delegates to the\n * flat-merge factory of ColumnOverriddenRecipe; subsequent `withSpecs`\n * calls merge at the Overridden level (one wrapper, no nesting).\n */\n withSpecs(overrides: SpecOverrides): ColumnRecipe {\n return ColumnOverriddenRecipe.wrap(this, overrides);\n }\n\n /**\n * Assembles the SpecQuery for this discovered hit by folding `key.path`\n * around the hit column.\n *\n * The hit (innermost) is built by inlining `columns[key.column].getQuery()`\n * — recursing into the hit's own recipe — so wrapping layers on the hit\n * (Overridden / Filtered / nested Discovered) appear in the produced tree.\n * The previous `pframeSpec.buildQuery` path was a flat\n * {@link PObjectId}-only call and could not express that.\n *\n * Linkers stay as plain column references on the linker side of\n * `linkerJoin` (the spec node has no slot for a query-side linker); the\n * linker's recipe id is used directly. The frame registered in\n * {@link getSpec} carries each recipe's final spec under that same id, so\n * the engine resolves linker axes from the post-projection spec.\n *\n * Path ordering matches {@link ColumnDiscoveredKey.path}: `path[0]` is\n * outermost, `path[N-1]` is closest to the hit. We fold from the inside\n * out — innermost wrap first — so the result lines up with that convention.\n *\n * `columnQualifications` / `queriesQualifications` are not emitted here —\n * qualifications live on a {@link SpecQueryJoinEntry} wrapper (lost on\n * unwrapping to {@link SpecQuery}). External consumers apply them at the\n * outer join via {@link getColumnQualifications} / {@link getQueriesQualifications}.\n */\n private buildSpecQuery(): SpecQuery {\n // Preserve the inner hit recipe's full query tree — it may carry\n // wrappers (specOverride / sliceAxes / nested linkerJoin) that the\n // host needs to apply correctly. We only rebrand the terminal column\n // leaf to this.id so two variants of the same physical hit reached via\n // different linker chains stay distinct columns in the engine output.\n const hitRecipe =\n this.columns[this.key.column] ??\n throwError(`ColumnDiscoveredRecipe.buildSpecQuery: missing column ${this.key.column}`);\n let query: SpecQuery = rebrandLeafId(hitRecipe.getQuery(), hitRecipe.id, this.id);\n const path = this.key.path ?? [];\n\n for (let i = path.length - 1; i >= 0; i--) {\n const linker =\n this.columns[path[i].column] ??\n throwError(\n `ColumnDiscoveredRecipe.buildSpecQuery: missing linker column ${path[i].column}`,\n );\n query = {\n type: \"linkerJoin\",\n linker: linker.getQuery(),\n secondary: [{ entry: query }],\n };\n }\n return query;\n }\n}\n\nfunction referencedUniIdsOf(key: ColumnDiscoveredKey): Set<ColumnUniversalId> {\n return new Set<ColumnUniversalId>([key.column, ...(key.path ?? []).map((item) => item.column)]);\n}\n"],"mappings":"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"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
const require_leaf_rebrand = require("./leaf_rebrand.cjs");
|
|
2
2
|
const require_index = require("./index.cjs");
|
|
3
|
+
const require_data_column = require("../data_column.cjs");
|
|
3
4
|
let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
|
|
4
5
|
//#region src/columns/column_recipes/column_overrided_recipe.ts
|
|
5
6
|
/**
|
|
@@ -23,8 +24,31 @@ var ColumnOverriddenRecipe = class ColumnOverriddenRecipe {
|
|
|
23
24
|
* `Overridden<Overridden<X>>` is produced.
|
|
24
25
|
*/
|
|
25
26
|
static wrap(col, overrides) {
|
|
26
|
-
if (col instanceof ColumnOverriddenRecipe) return
|
|
27
|
-
return
|
|
27
|
+
if (col instanceof ColumnOverriddenRecipe) return ColumnOverriddenRecipe.build(col.inner, (0, _milaboratories_pl_model_common.mergeSpecOverrides)(col.overrides, overrides));
|
|
28
|
+
return ColumnOverriddenRecipe.build(col, overrides);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Pick the variant from the inner recipe: data-bearing inner →
|
|
32
|
+
* {@link DataColumnOverriddenRecipe}, otherwise the plain wrapper.
|
|
33
|
+
*
|
|
34
|
+
* The choice is **structural**, not a readiness check — it follows from
|
|
35
|
+
* which kind of recipe `inner` is, which in turn follows from the id alone
|
|
36
|
+
* (a bare `PObjectId` source is a leaf, anything else is not). So the same
|
|
37
|
+
* id always yields the same class, whether it was built via `withSpecs` or
|
|
38
|
+
* parsed from a string, and recipes stay value-objects that are equal iff
|
|
39
|
+
* their ids match.
|
|
40
|
+
*
|
|
41
|
+
* Re-deriving from `inner` on every build is also what keeps the merge path
|
|
42
|
+
* honest: `overridden.withSpecs(a).withSpecs(b)` cannot silently drop the
|
|
43
|
+
* data-bearing variant.
|
|
44
|
+
*
|
|
45
|
+
* Discriminated by method presence rather than `instanceof DataColumnImpl`
|
|
46
|
+
* to keep this module free of a runtime import cycle with `../data_column`.
|
|
47
|
+
* By the flat-merge invariant `inner` is never an Overridden, so the only
|
|
48
|
+
* recipe kind reaching here that carries `getData` is the leaf.
|
|
49
|
+
*/
|
|
50
|
+
static build(inner, overrides) {
|
|
51
|
+
return require_data_column.isDataColumn(inner) ? new DataColumnOverriddenRecipe(inner, overrides) : new ColumnOverriddenRecipe(inner, overrides);
|
|
28
52
|
}
|
|
29
53
|
/**
|
|
30
54
|
* Static counterpart to {@link wrap}: returns the resolution status of a
|
|
@@ -95,7 +119,28 @@ var ColumnOverriddenRecipe = class ColumnOverriddenRecipe {
|
|
|
95
119
|
return ColumnOverriddenRecipe.wrap(this, overrides);
|
|
96
120
|
}
|
|
97
121
|
};
|
|
122
|
+
/**
|
|
123
|
+
* The variant produced when the wrapped recipe is itself data-bearing.
|
|
124
|
+
*
|
|
125
|
+
* Overrides are a pure spec patch — they never reshape the data — so the inner
|
|
126
|
+
* column's data stays consistent with this recipe's spec and is passed
|
|
127
|
+
* straight through. Which variant you get is decided once, at construction:
|
|
128
|
+
* see {@link build}.
|
|
129
|
+
*
|
|
130
|
+
* Not something callers name. Narrow with `hasReachableData(recipe)`, which
|
|
131
|
+
* yields the {@link DataColumnRecipe} interface.
|
|
132
|
+
*/
|
|
133
|
+
var DataColumnOverriddenRecipe = class extends ColumnOverriddenRecipe {
|
|
134
|
+
/**
|
|
135
|
+
* Safe by construction: {@link build} only picks this class when the inner
|
|
136
|
+
* recipe exposes `getData`.
|
|
137
|
+
*/
|
|
138
|
+
getData() {
|
|
139
|
+
return this.getInner().getData();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
98
142
|
//#endregion
|
|
99
143
|
exports.ColumnOverriddenRecipe = ColumnOverriddenRecipe;
|
|
144
|
+
exports.DataColumnOverriddenRecipe = DataColumnOverriddenRecipe;
|
|
100
145
|
|
|
101
146
|
//# sourceMappingURL=column_overrided_recipe.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column_overrided_recipe.cjs","names":["ColumnRecipe","rebrandLeafId"],"sources":["../../../src/columns/column_recipes/column_overrided_recipe.ts"],"sourcesContent":["import {\n applySpecOverrides,\n createColumnOverriddenId,\n mergeSpecOverrides,\n type ColumnOverriddenId,\n type ColumnOverriddenKey,\n type ColumnUniversalId,\n type PColumnSpec,\n type PObjectId,\n type SpecOverrides,\n type SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport type { GlobalCfgRenderCtx } from \"../../render/internal\";\nimport type { ColumnFieldStatus, ColumnResolutionStatus } from \"./types\";\nimport { ColumnRecipe } from \"./index\";\nimport { Column } from \"../column\";\nimport { rebrandLeafId } from \"./leaf_rebrand\";\n\n/**\n * A recipe whose id is not an Overridden wrap — valid `source` for Overridden.\n * Mirrors the spec-level invariant on {@link ColumnOverriddenKey.source}.\n */\ntype NonOverriddenColumn = Column<Exclude<ColumnUniversalId, ColumnOverriddenId>>;\n\n/**\n * Recipe wrapper that overlays {@link SpecOverrides} on top of any other\n * recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.\n *\n * Flat-merge invariant: `inner` is never another {@link ColumnOverriddenRecipe}.\n * Repeated overrides go through {@link wrap} / {@link withSpecs}, which merge\n * `specOverrides` at the current level and keep wrapper depth constant.\n *\n * This invariant matches the one enforced inside `unwrapOverrides` from\n * pl-model-common: it explicitly throws on a nested override-wrap.\n */\nexport class ColumnOverriddenRecipe implements
|
|
1
|
+
{"version":3,"file":"column_overrided_recipe.cjs","names":["isDataColumn","ColumnRecipe","rebrandLeafId"],"sources":["../../../src/columns/column_recipes/column_overrided_recipe.ts"],"sourcesContent":["import {\n applySpecOverrides,\n createColumnOverriddenId,\n mergeSpecOverrides,\n type ColumnOverriddenId,\n type ColumnOverriddenKey,\n type ColumnUniversalId,\n type PColumnSpec,\n type PObjectId,\n type SpecOverrides,\n type SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport type { GlobalCfgRenderCtx } from \"../../render/internal\";\nimport { type DataColumnRecipe, type ColumnData, isDataColumn } from \"../data_column\";\nimport type { ColumnFieldStatus, ColumnResolutionStatus } from \"./types\";\nimport { ColumnRecipe } from \"./index\";\nimport { Column } from \"../column\";\nimport { rebrandLeafId } from \"./leaf_rebrand\";\n\n/**\n * A recipe whose id is not an Overridden wrap — valid `source` for Overridden.\n * Mirrors the spec-level invariant on {@link ColumnOverriddenKey.source}.\n */\ntype NonOverriddenColumn = Column<Exclude<ColumnUniversalId, ColumnOverriddenId>>;\n\n/**\n * Recipe wrapper that overlays {@link SpecOverrides} on top of any other\n * recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.\n *\n * Flat-merge invariant: `inner` is never another {@link ColumnOverriddenRecipe}.\n * Repeated overrides go through {@link wrap} / {@link withSpecs}, which merge\n * `specOverrides` at the current level and keep wrapper depth constant.\n *\n * This invariant matches the one enforced inside `unwrapOverrides` from\n * pl-model-common: it explicitly throws on a nested override-wrap.\n */\nexport class ColumnOverriddenRecipe implements ColumnRecipe<ColumnOverriddenId> {\n /**\n * Wrap any recipe with overrides. If `inner` is already a\n * {@link ColumnOverriddenRecipe}, merges `overrides` into the existing ones\n * and returns a new Overridden sharing the original `inner`. No\n * `Overridden<Overridden<X>>` is produced.\n */\n static wrap(col: Column, overrides: SpecOverrides): ColumnOverriddenRecipe {\n if (col instanceof ColumnOverriddenRecipe) {\n return ColumnOverriddenRecipe.build(col.inner, mergeSpecOverrides(col.overrides, overrides));\n }\n // `inner` is not an Overridden wrap (the `instanceof` branch above handles\n // that). Narrow the id union here so the constructor parameter stays\n // honest with `ColumnOverriddenKey.source`.\n return ColumnOverriddenRecipe.build(col as NonOverriddenColumn, overrides);\n }\n\n /**\n * Pick the variant from the inner recipe: data-bearing inner →\n * {@link DataColumnOverriddenRecipe}, otherwise the plain wrapper.\n *\n * The choice is **structural**, not a readiness check — it follows from\n * which kind of recipe `inner` is, which in turn follows from the id alone\n * (a bare `PObjectId` source is a leaf, anything else is not). So the same\n * id always yields the same class, whether it was built via `withSpecs` or\n * parsed from a string, and recipes stay value-objects that are equal iff\n * their ids match.\n *\n * Re-deriving from `inner` on every build is also what keeps the merge path\n * honest: `overridden.withSpecs(a).withSpecs(b)` cannot silently drop the\n * data-bearing variant.\n *\n * Discriminated by method presence rather than `instanceof DataColumnImpl`\n * to keep this module free of a runtime import cycle with `../data_column`.\n * By the flat-merge invariant `inner` is never an Overridden, so the only\n * recipe kind reaching here that carries `getData` is the leaf.\n */\n private static build(\n inner: NonOverriddenColumn,\n overrides: SpecOverrides,\n ): ColumnOverriddenRecipe {\n return isDataColumn(inner)\n ? new DataColumnOverriddenRecipe(inner, overrides)\n : new ColumnOverriddenRecipe(inner, overrides);\n }\n\n /**\n * Static counterpart to {@link wrap}: returns the resolution status of a\n * {@link ColumnOverriddenKey} without constructing the recipe. Overrides\n * do not add references — status collapses to the source's status.\n */\n static getStatusByKey(\n key: ColumnOverriddenKey,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n ): ColumnResolutionStatus {\n return ColumnRecipe.getStatus(key.source, opts);\n }\n\n readonly id: ColumnOverriddenId;\n private specCache?: { readonly value: PColumnSpec };\n private queryCache?: { readonly value: SpecQuery };\n private dataStatusCache?: { readonly value: ColumnFieldStatus };\n\n protected constructor(\n private readonly inner: NonOverriddenColumn,\n private readonly overrides: SpecOverrides,\n ) {\n this.id = createColumnOverriddenId({\n source: inner.id,\n specOverrides: overrides,\n });\n }\n\n /** Wrapped recipe — exposed so external walkers can descend. */\n getInner(): Column {\n return this.inner;\n }\n\n /**\n * `inner` owns all references; overrides are a pure spec patch and do not\n * introduce new column refs.\n */\n getReferencedIds(): PObjectId[] {\n return this.inner.getReferencedIds();\n }\n\n getDataStatus(): ColumnFieldStatus {\n if (this.dataStatusCache === undefined) {\n this.dataStatusCache = { value: this.inner.getDataStatus() };\n }\n return this.dataStatusCache.value;\n }\n\n /**\n * Take the inner spec and overlay our overrides. `applySpecOverrides`\n * extracts the overrides from `this.id` itself.\n */\n getSpec(): PColumnSpec {\n if (this.specCache === undefined) {\n this.specCache = { value: applySpecOverrides(this.inner.getSpec(), this.id) };\n }\n return this.specCache.value;\n }\n\n /**\n * Emit a client-side `specOverride` node wrapping the inner query.\n *\n * This is a structural-but-collapsible node: it carries the override\n * patch through the query tree so consumers see the full recipe shape,\n * but it is collapsed at the host boundary (`resolvePColumn`) before\n * the query reaches pframe-engine. The engine never sees this node.\n *\n * Overrides do not change query topology — they are a pure spec patch.\n */\n getQuery(): SpecQuery {\n if (this.queryCache === undefined) {\n // Rebrand the inner column leaf to this.id (rich Overridden id) so\n // filter/sort references emitted with this recipe's id match the\n // leaf the engine sees. The specOverride node still wraps the leaf\n // and is collapsed at the host boundary into a spec patch on the\n // resolved PColumn.\n this.queryCache = {\n value: {\n type: \"specOverride\",\n input: rebrandLeafId(this.inner.getQuery(), this.inner.id, this.id),\n override: this.overrides,\n },\n };\n }\n return this.queryCache.value;\n }\n\n /**\n * Flat merge: new overrides merge with existing ones; `inner` is unchanged.\n * The result is an Overridden of the same depth.\n */\n withSpecs(overrides: SpecOverrides): Column {\n return ColumnOverriddenRecipe.wrap(this, overrides);\n }\n}\n\n/**\n * The variant produced when the wrapped recipe is itself data-bearing.\n *\n * Overrides are a pure spec patch — they never reshape the data — so the inner\n * column's data stays consistent with this recipe's spec and is passed\n * straight through. Which variant you get is decided once, at construction:\n * see {@link build}.\n *\n * Not something callers name. Narrow with `hasReachableData(recipe)`, which\n * yields the {@link DataColumnRecipe} interface.\n */\nexport class DataColumnOverriddenRecipe\n extends ColumnOverriddenRecipe\n implements DataColumnRecipe<ColumnOverriddenId>\n{\n /**\n * Safe by construction: {@link build} only picks this class when the inner\n * recipe exposes `getData`.\n */\n getData(): ColumnData {\n return (this.getInner() as DataColumnRecipe).getData();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoCA,IAAa,yBAAb,MAAa,uBAAmE;CAgE3D;CACA;;;;;;;CA1DnB,OAAO,KAAK,KAAa,WAAkD;EACzE,IAAI,eAAe,wBACjB,OAAO,uBAAuB,MAAM,IAAI,QAAA,GAAA,gCAAA,mBAAA,CAA0B,IAAI,WAAW,SAAS,CAAC;EAK7F,OAAO,uBAAuB,MAAM,KAA4B,SAAS;CAC3E;;;;;;;;;;;;;;;;;;;;;CAsBA,OAAe,MACb,OACA,WACwB;EACxB,OAAOA,oBAAAA,aAAa,KAAK,IACrB,IAAI,2BAA2B,OAAO,SAAS,IAC/C,IAAI,uBAAuB,OAAO,SAAS;CACjD;;;;;;CAOA,OAAO,eACL,KACA,OAAqC,CAAC,GACd;EACxB,OAAOC,cAAAA,aAAa,UAAU,IAAI,QAAQ,IAAI;CAChD;CAEA;CACA;CACA;CACA;CAEA,YACE,OACA,WACA;EAFiB,KAAA,QAAA;EACA,KAAA,YAAA;EAEjB,KAAK,MAAA,GAAA,gCAAA,yBAAA,CAA8B;GACjC,QAAQ,MAAM;GACd,eAAe;EACjB,CAAC;CACH;;CAGA,WAAmB;EACjB,OAAO,KAAK;CACd;;;;;CAMA,mBAAgC;EAC9B,OAAO,KAAK,MAAM,iBAAiB;CACrC;CAEA,gBAAmC;EACjC,IAAI,KAAK,oBAAoB,KAAA,GAC3B,KAAK,kBAAkB,EAAE,OAAO,KAAK,MAAM,cAAc,EAAE;EAE7D,OAAO,KAAK,gBAAgB;CAC9B;;;;;CAMA,UAAuB;EACrB,IAAI,KAAK,cAAc,KAAA,GACrB,KAAK,YAAY,EAAE,QAAA,GAAA,gCAAA,mBAAA,CAA0B,KAAK,MAAM,QAAQ,GAAG,KAAK,EAAE,EAAE;EAE9E,OAAO,KAAK,UAAU;CACxB;;;;;;;;;;;CAYA,WAAsB;EACpB,IAAI,KAAK,eAAe,KAAA,GAMtB,KAAK,aAAa,EAChB,OAAO;GACL,MAAM;GACN,OAAOC,qBAAAA,cAAc,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,IAAI,KAAK,EAAE;GAClE,UAAU,KAAK;EACjB,EACF;EAEF,OAAO,KAAK,WAAW;CACzB;;;;;CAMA,UAAU,WAAkC;EAC1C,OAAO,uBAAuB,KAAK,MAAM,SAAS;CACpD;AACF;;;;;;;;;;;;AAaA,IAAa,6BAAb,cACU,uBAEV;;;;;CAKE,UAAsB;EACpB,OAAQ,KAAK,SAAS,CAAC,CAAsB,QAAQ;CACvD;AACF"}
|
|
@@ -1,9 +1,15 @@
|
|
|
1
1
|
import { GlobalCfgRenderCtx } from "../../render/internal.js";
|
|
2
2
|
import { ColumnFieldStatus, ColumnResolutionStatus } from "./types.js";
|
|
3
3
|
import { Column } from "../column.js";
|
|
4
|
-
import {
|
|
4
|
+
import { ColumnRecipe } from "./index.js";
|
|
5
|
+
import { ColumnOverriddenId, ColumnOverriddenKey, ColumnUniversalId, PColumnSpec, PObjectId, SpecOverrides, SpecQuery } from "@milaboratories/pl-model-common";
|
|
5
6
|
|
|
6
7
|
//#region src/columns/column_recipes/column_overrided_recipe.d.ts
|
|
8
|
+
/**
|
|
9
|
+
* A recipe whose id is not an Overridden wrap — valid `source` for Overridden.
|
|
10
|
+
* Mirrors the spec-level invariant on {@link ColumnOverriddenKey.source}.
|
|
11
|
+
*/
|
|
12
|
+
type NonOverriddenColumn = Column<Exclude<ColumnUniversalId, ColumnOverriddenId>>;
|
|
7
13
|
/**
|
|
8
14
|
* Recipe wrapper that overlays {@link SpecOverrides} on top of any other
|
|
9
15
|
* recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.
|
|
@@ -15,7 +21,7 @@ import { ColumnOverriddenId, ColumnOverriddenKey, PColumnSpec, PObjectId, SpecOv
|
|
|
15
21
|
* This invariant matches the one enforced inside `unwrapOverrides` from
|
|
16
22
|
* pl-model-common: it explicitly throws on a nested override-wrap.
|
|
17
23
|
*/
|
|
18
|
-
declare class ColumnOverriddenRecipe implements
|
|
24
|
+
declare class ColumnOverriddenRecipe implements ColumnRecipe<ColumnOverriddenId> {
|
|
19
25
|
private readonly inner;
|
|
20
26
|
private readonly overrides;
|
|
21
27
|
/**
|
|
@@ -25,6 +31,27 @@ declare class ColumnOverriddenRecipe implements Column<ColumnOverriddenId> {
|
|
|
25
31
|
* `Overridden<Overridden<X>>` is produced.
|
|
26
32
|
*/
|
|
27
33
|
static wrap(col: Column, overrides: SpecOverrides): ColumnOverriddenRecipe;
|
|
34
|
+
/**
|
|
35
|
+
* Pick the variant from the inner recipe: data-bearing inner →
|
|
36
|
+
* {@link DataColumnOverriddenRecipe}, otherwise the plain wrapper.
|
|
37
|
+
*
|
|
38
|
+
* The choice is **structural**, not a readiness check — it follows from
|
|
39
|
+
* which kind of recipe `inner` is, which in turn follows from the id alone
|
|
40
|
+
* (a bare `PObjectId` source is a leaf, anything else is not). So the same
|
|
41
|
+
* id always yields the same class, whether it was built via `withSpecs` or
|
|
42
|
+
* parsed from a string, and recipes stay value-objects that are equal iff
|
|
43
|
+
* their ids match.
|
|
44
|
+
*
|
|
45
|
+
* Re-deriving from `inner` on every build is also what keeps the merge path
|
|
46
|
+
* honest: `overridden.withSpecs(a).withSpecs(b)` cannot silently drop the
|
|
47
|
+
* data-bearing variant.
|
|
48
|
+
*
|
|
49
|
+
* Discriminated by method presence rather than `instanceof DataColumnImpl`
|
|
50
|
+
* to keep this module free of a runtime import cycle with `../data_column`.
|
|
51
|
+
* By the flat-merge invariant `inner` is never an Overridden, so the only
|
|
52
|
+
* recipe kind reaching here that carries `getData` is the leaf.
|
|
53
|
+
*/
|
|
54
|
+
private static build;
|
|
28
55
|
/**
|
|
29
56
|
* Static counterpart to {@link wrap}: returns the resolution status of a
|
|
30
57
|
* {@link ColumnOverriddenKey} without constructing the recipe. Overrides
|
|
@@ -37,7 +64,7 @@ declare class ColumnOverriddenRecipe implements Column<ColumnOverriddenId> {
|
|
|
37
64
|
private specCache?;
|
|
38
65
|
private queryCache?;
|
|
39
66
|
private dataStatusCache?;
|
|
40
|
-
|
|
67
|
+
protected constructor(inner: NonOverriddenColumn, overrides: SpecOverrides);
|
|
41
68
|
/** Wrapped recipe — exposed so external walkers can descend. */
|
|
42
69
|
getInner(): Column;
|
|
43
70
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column_overrided_recipe.d.ts","names":[],"sources":["../../../src/columns/column_recipes/column_overrided_recipe.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"column_overrided_recipe.d.ts","names":[],"sources":["../../../src/columns/column_recipes/column_overrided_recipe.ts"],"mappings":";;;;;;;;;AAgBmC;;KAO9B,mBAAA,GAAsB,MAAA,CAAO,OAAA,CAAQ,iBAAA,EAAmB,kBAAA;;;;;;;;;;;;cAahD,sBAAA,YAAkC,YAAA,CAAa,kBAAA;EAAA,iBAgEvC,KAAA;EAAA,iBACA,SAAA;;;;;;;SA1DZ,IAAA,CAAK,GAAA,EAAK,MAAA,EAAQ,SAAA,EAAW,aAAA,GAAgB,sBAAA;EA+CjD;;;;;;;;;;;;;;;;;;;;EAAA,eAjBY,KAAA;EA9BqB;;;;;EAAA,OA4C7B,cAAA,CACL,GAAA,EAAK,mBAAA,EACL,IAAA;IAAQ,GAAA,GAAM,kBAAA;EAAA,IACb,sBAAA;EAAA,SAIM,EAAA,EAAI,kBAAA;EAAA,QACL,SAAA;EAAA,QACA,UAAA;EAAA,QACA,eAAA;EAAA,UAEC,WAAA,CACU,KAAA,EAAO,mBAAA,EACP,SAAA,EAAW,aAAA;EANtB;EAeR,QAAA,IAAY,MAAA;EAbJ;;;;EAqBR,gBAAA,IAAoB,SAAA;EAIpB,aAAA,IAAiB,iBAAA;EAZjB;;;;EAuBA,OAAA,IAAW,WAAA;EAXM;;;;;;;;;;EA4BjB,QAAA,IAAY,SAAA;;;;;EAsBZ,SAAA,CAAU,SAAA,EAAW,aAAA,GAAgB,MAAA;AAAA"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { rebrandLeafId } from "./leaf_rebrand.js";
|
|
2
2
|
import { ColumnRecipe } from "./index.js";
|
|
3
|
+
import { isDataColumn } from "../data_column.js";
|
|
3
4
|
import { applySpecOverrides, createColumnOverriddenId, mergeSpecOverrides } from "@milaboratories/pl-model-common";
|
|
4
5
|
//#region src/columns/column_recipes/column_overrided_recipe.ts
|
|
5
6
|
/**
|
|
@@ -23,8 +24,31 @@ var ColumnOverriddenRecipe = class ColumnOverriddenRecipe {
|
|
|
23
24
|
* `Overridden<Overridden<X>>` is produced.
|
|
24
25
|
*/
|
|
25
26
|
static wrap(col, overrides) {
|
|
26
|
-
if (col instanceof ColumnOverriddenRecipe) return
|
|
27
|
-
return
|
|
27
|
+
if (col instanceof ColumnOverriddenRecipe) return ColumnOverriddenRecipe.build(col.inner, mergeSpecOverrides(col.overrides, overrides));
|
|
28
|
+
return ColumnOverriddenRecipe.build(col, overrides);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Pick the variant from the inner recipe: data-bearing inner →
|
|
32
|
+
* {@link DataColumnOverriddenRecipe}, otherwise the plain wrapper.
|
|
33
|
+
*
|
|
34
|
+
* The choice is **structural**, not a readiness check — it follows from
|
|
35
|
+
* which kind of recipe `inner` is, which in turn follows from the id alone
|
|
36
|
+
* (a bare `PObjectId` source is a leaf, anything else is not). So the same
|
|
37
|
+
* id always yields the same class, whether it was built via `withSpecs` or
|
|
38
|
+
* parsed from a string, and recipes stay value-objects that are equal iff
|
|
39
|
+
* their ids match.
|
|
40
|
+
*
|
|
41
|
+
* Re-deriving from `inner` on every build is also what keeps the merge path
|
|
42
|
+
* honest: `overridden.withSpecs(a).withSpecs(b)` cannot silently drop the
|
|
43
|
+
* data-bearing variant.
|
|
44
|
+
*
|
|
45
|
+
* Discriminated by method presence rather than `instanceof DataColumnImpl`
|
|
46
|
+
* to keep this module free of a runtime import cycle with `../data_column`.
|
|
47
|
+
* By the flat-merge invariant `inner` is never an Overridden, so the only
|
|
48
|
+
* recipe kind reaching here that carries `getData` is the leaf.
|
|
49
|
+
*/
|
|
50
|
+
static build(inner, overrides) {
|
|
51
|
+
return isDataColumn(inner) ? new DataColumnOverriddenRecipe(inner, overrides) : new ColumnOverriddenRecipe(inner, overrides);
|
|
28
52
|
}
|
|
29
53
|
/**
|
|
30
54
|
* Static counterpart to {@link wrap}: returns the resolution status of a
|
|
@@ -95,7 +119,27 @@ var ColumnOverriddenRecipe = class ColumnOverriddenRecipe {
|
|
|
95
119
|
return ColumnOverriddenRecipe.wrap(this, overrides);
|
|
96
120
|
}
|
|
97
121
|
};
|
|
122
|
+
/**
|
|
123
|
+
* The variant produced when the wrapped recipe is itself data-bearing.
|
|
124
|
+
*
|
|
125
|
+
* Overrides are a pure spec patch — they never reshape the data — so the inner
|
|
126
|
+
* column's data stays consistent with this recipe's spec and is passed
|
|
127
|
+
* straight through. Which variant you get is decided once, at construction:
|
|
128
|
+
* see {@link build}.
|
|
129
|
+
*
|
|
130
|
+
* Not something callers name. Narrow with `hasReachableData(recipe)`, which
|
|
131
|
+
* yields the {@link DataColumnRecipe} interface.
|
|
132
|
+
*/
|
|
133
|
+
var DataColumnOverriddenRecipe = class extends ColumnOverriddenRecipe {
|
|
134
|
+
/**
|
|
135
|
+
* Safe by construction: {@link build} only picks this class when the inner
|
|
136
|
+
* recipe exposes `getData`.
|
|
137
|
+
*/
|
|
138
|
+
getData() {
|
|
139
|
+
return this.getInner().getData();
|
|
140
|
+
}
|
|
141
|
+
};
|
|
98
142
|
//#endregion
|
|
99
|
-
export { ColumnOverriddenRecipe };
|
|
143
|
+
export { ColumnOverriddenRecipe, DataColumnOverriddenRecipe };
|
|
100
144
|
|
|
101
145
|
//# sourceMappingURL=column_overrided_recipe.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"column_overrided_recipe.js","names":[],"sources":["../../../src/columns/column_recipes/column_overrided_recipe.ts"],"sourcesContent":["import {\n applySpecOverrides,\n createColumnOverriddenId,\n mergeSpecOverrides,\n type ColumnOverriddenId,\n type ColumnOverriddenKey,\n type ColumnUniversalId,\n type PColumnSpec,\n type PObjectId,\n type SpecOverrides,\n type SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport type { GlobalCfgRenderCtx } from \"../../render/internal\";\nimport type { ColumnFieldStatus, ColumnResolutionStatus } from \"./types\";\nimport { ColumnRecipe } from \"./index\";\nimport { Column } from \"../column\";\nimport { rebrandLeafId } from \"./leaf_rebrand\";\n\n/**\n * A recipe whose id is not an Overridden wrap — valid `source` for Overridden.\n * Mirrors the spec-level invariant on {@link ColumnOverriddenKey.source}.\n */\ntype NonOverriddenColumn = Column<Exclude<ColumnUniversalId, ColumnOverriddenId>>;\n\n/**\n * Recipe wrapper that overlays {@link SpecOverrides} on top of any other\n * recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.\n *\n * Flat-merge invariant: `inner` is never another {@link ColumnOverriddenRecipe}.\n * Repeated overrides go through {@link wrap} / {@link withSpecs}, which merge\n * `specOverrides` at the current level and keep wrapper depth constant.\n *\n * This invariant matches the one enforced inside `unwrapOverrides` from\n * pl-model-common: it explicitly throws on a nested override-wrap.\n */\nexport class ColumnOverriddenRecipe implements
|
|
1
|
+
{"version":3,"file":"column_overrided_recipe.js","names":[],"sources":["../../../src/columns/column_recipes/column_overrided_recipe.ts"],"sourcesContent":["import {\n applySpecOverrides,\n createColumnOverriddenId,\n mergeSpecOverrides,\n type ColumnOverriddenId,\n type ColumnOverriddenKey,\n type ColumnUniversalId,\n type PColumnSpec,\n type PObjectId,\n type SpecOverrides,\n type SpecQuery,\n} from \"@milaboratories/pl-model-common\";\nimport type { GlobalCfgRenderCtx } from \"../../render/internal\";\nimport { type DataColumnRecipe, type ColumnData, isDataColumn } from \"../data_column\";\nimport type { ColumnFieldStatus, ColumnResolutionStatus } from \"./types\";\nimport { ColumnRecipe } from \"./index\";\nimport { Column } from \"../column\";\nimport { rebrandLeafId } from \"./leaf_rebrand\";\n\n/**\n * A recipe whose id is not an Overridden wrap — valid `source` for Overridden.\n * Mirrors the spec-level invariant on {@link ColumnOverriddenKey.source}.\n */\ntype NonOverriddenColumn = Column<Exclude<ColumnUniversalId, ColumnOverriddenId>>;\n\n/**\n * Recipe wrapper that overlays {@link SpecOverrides} on top of any other\n * recipe. The id is `ColumnOverriddenKey { source: inner.id, specOverrides }`.\n *\n * Flat-merge invariant: `inner` is never another {@link ColumnOverriddenRecipe}.\n * Repeated overrides go through {@link wrap} / {@link withSpecs}, which merge\n * `specOverrides` at the current level and keep wrapper depth constant.\n *\n * This invariant matches the one enforced inside `unwrapOverrides` from\n * pl-model-common: it explicitly throws on a nested override-wrap.\n */\nexport class ColumnOverriddenRecipe implements ColumnRecipe<ColumnOverriddenId> {\n /**\n * Wrap any recipe with overrides. If `inner` is already a\n * {@link ColumnOverriddenRecipe}, merges `overrides` into the existing ones\n * and returns a new Overridden sharing the original `inner`. No\n * `Overridden<Overridden<X>>` is produced.\n */\n static wrap(col: Column, overrides: SpecOverrides): ColumnOverriddenRecipe {\n if (col instanceof ColumnOverriddenRecipe) {\n return ColumnOverriddenRecipe.build(col.inner, mergeSpecOverrides(col.overrides, overrides));\n }\n // `inner` is not an Overridden wrap (the `instanceof` branch above handles\n // that). Narrow the id union here so the constructor parameter stays\n // honest with `ColumnOverriddenKey.source`.\n return ColumnOverriddenRecipe.build(col as NonOverriddenColumn, overrides);\n }\n\n /**\n * Pick the variant from the inner recipe: data-bearing inner →\n * {@link DataColumnOverriddenRecipe}, otherwise the plain wrapper.\n *\n * The choice is **structural**, not a readiness check — it follows from\n * which kind of recipe `inner` is, which in turn follows from the id alone\n * (a bare `PObjectId` source is a leaf, anything else is not). So the same\n * id always yields the same class, whether it was built via `withSpecs` or\n * parsed from a string, and recipes stay value-objects that are equal iff\n * their ids match.\n *\n * Re-deriving from `inner` on every build is also what keeps the merge path\n * honest: `overridden.withSpecs(a).withSpecs(b)` cannot silently drop the\n * data-bearing variant.\n *\n * Discriminated by method presence rather than `instanceof DataColumnImpl`\n * to keep this module free of a runtime import cycle with `../data_column`.\n * By the flat-merge invariant `inner` is never an Overridden, so the only\n * recipe kind reaching here that carries `getData` is the leaf.\n */\n private static build(\n inner: NonOverriddenColumn,\n overrides: SpecOverrides,\n ): ColumnOverriddenRecipe {\n return isDataColumn(inner)\n ? new DataColumnOverriddenRecipe(inner, overrides)\n : new ColumnOverriddenRecipe(inner, overrides);\n }\n\n /**\n * Static counterpart to {@link wrap}: returns the resolution status of a\n * {@link ColumnOverriddenKey} without constructing the recipe. Overrides\n * do not add references — status collapses to the source's status.\n */\n static getStatusByKey(\n key: ColumnOverriddenKey,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n ): ColumnResolutionStatus {\n return ColumnRecipe.getStatus(key.source, opts);\n }\n\n readonly id: ColumnOverriddenId;\n private specCache?: { readonly value: PColumnSpec };\n private queryCache?: { readonly value: SpecQuery };\n private dataStatusCache?: { readonly value: ColumnFieldStatus };\n\n protected constructor(\n private readonly inner: NonOverriddenColumn,\n private readonly overrides: SpecOverrides,\n ) {\n this.id = createColumnOverriddenId({\n source: inner.id,\n specOverrides: overrides,\n });\n }\n\n /** Wrapped recipe — exposed so external walkers can descend. */\n getInner(): Column {\n return this.inner;\n }\n\n /**\n * `inner` owns all references; overrides are a pure spec patch and do not\n * introduce new column refs.\n */\n getReferencedIds(): PObjectId[] {\n return this.inner.getReferencedIds();\n }\n\n getDataStatus(): ColumnFieldStatus {\n if (this.dataStatusCache === undefined) {\n this.dataStatusCache = { value: this.inner.getDataStatus() };\n }\n return this.dataStatusCache.value;\n }\n\n /**\n * Take the inner spec and overlay our overrides. `applySpecOverrides`\n * extracts the overrides from `this.id` itself.\n */\n getSpec(): PColumnSpec {\n if (this.specCache === undefined) {\n this.specCache = { value: applySpecOverrides(this.inner.getSpec(), this.id) };\n }\n return this.specCache.value;\n }\n\n /**\n * Emit a client-side `specOverride` node wrapping the inner query.\n *\n * This is a structural-but-collapsible node: it carries the override\n * patch through the query tree so consumers see the full recipe shape,\n * but it is collapsed at the host boundary (`resolvePColumn`) before\n * the query reaches pframe-engine. The engine never sees this node.\n *\n * Overrides do not change query topology — they are a pure spec patch.\n */\n getQuery(): SpecQuery {\n if (this.queryCache === undefined) {\n // Rebrand the inner column leaf to this.id (rich Overridden id) so\n // filter/sort references emitted with this recipe's id match the\n // leaf the engine sees. The specOverride node still wraps the leaf\n // and is collapsed at the host boundary into a spec patch on the\n // resolved PColumn.\n this.queryCache = {\n value: {\n type: \"specOverride\",\n input: rebrandLeafId(this.inner.getQuery(), this.inner.id, this.id),\n override: this.overrides,\n },\n };\n }\n return this.queryCache.value;\n }\n\n /**\n * Flat merge: new overrides merge with existing ones; `inner` is unchanged.\n * The result is an Overridden of the same depth.\n */\n withSpecs(overrides: SpecOverrides): Column {\n return ColumnOverriddenRecipe.wrap(this, overrides);\n }\n}\n\n/**\n * The variant produced when the wrapped recipe is itself data-bearing.\n *\n * Overrides are a pure spec patch — they never reshape the data — so the inner\n * column's data stays consistent with this recipe's spec and is passed\n * straight through. Which variant you get is decided once, at construction:\n * see {@link build}.\n *\n * Not something callers name. Narrow with `hasReachableData(recipe)`, which\n * yields the {@link DataColumnRecipe} interface.\n */\nexport class DataColumnOverriddenRecipe\n extends ColumnOverriddenRecipe\n implements DataColumnRecipe<ColumnOverriddenId>\n{\n /**\n * Safe by construction: {@link build} only picks this class when the inner\n * recipe exposes `getData`.\n */\n getData(): ColumnData {\n return (this.getInner() as DataColumnRecipe).getData();\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;AAoCA,IAAa,yBAAb,MAAa,uBAAmE;CAgE3D;CACA;;;;;;;CA1DnB,OAAO,KAAK,KAAa,WAAkD;EACzE,IAAI,eAAe,wBACjB,OAAO,uBAAuB,MAAM,IAAI,OAAO,mBAAmB,IAAI,WAAW,SAAS,CAAC;EAK7F,OAAO,uBAAuB,MAAM,KAA4B,SAAS;CAC3E;;;;;;;;;;;;;;;;;;;;;CAsBA,OAAe,MACb,OACA,WACwB;EACxB,OAAO,aAAa,KAAK,IACrB,IAAI,2BAA2B,OAAO,SAAS,IAC/C,IAAI,uBAAuB,OAAO,SAAS;CACjD;;;;;;CAOA,OAAO,eACL,KACA,OAAqC,CAAC,GACd;EACxB,OAAO,aAAa,UAAU,IAAI,QAAQ,IAAI;CAChD;CAEA;CACA;CACA;CACA;CAEA,YACE,OACA,WACA;EAFiB,KAAA,QAAA;EACA,KAAA,YAAA;EAEjB,KAAK,KAAK,yBAAyB;GACjC,QAAQ,MAAM;GACd,eAAe;EACjB,CAAC;CACH;;CAGA,WAAmB;EACjB,OAAO,KAAK;CACd;;;;;CAMA,mBAAgC;EAC9B,OAAO,KAAK,MAAM,iBAAiB;CACrC;CAEA,gBAAmC;EACjC,IAAI,KAAK,oBAAoB,KAAA,GAC3B,KAAK,kBAAkB,EAAE,OAAO,KAAK,MAAM,cAAc,EAAE;EAE7D,OAAO,KAAK,gBAAgB;CAC9B;;;;;CAMA,UAAuB;EACrB,IAAI,KAAK,cAAc,KAAA,GACrB,KAAK,YAAY,EAAE,OAAO,mBAAmB,KAAK,MAAM,QAAQ,GAAG,KAAK,EAAE,EAAE;EAE9E,OAAO,KAAK,UAAU;CACxB;;;;;;;;;;;CAYA,WAAsB;EACpB,IAAI,KAAK,eAAe,KAAA,GAMtB,KAAK,aAAa,EAChB,OAAO;GACL,MAAM;GACN,OAAO,cAAc,KAAK,MAAM,SAAS,GAAG,KAAK,MAAM,IAAI,KAAK,EAAE;GAClE,UAAU,KAAK;EACjB,EACF;EAEF,OAAO,KAAK,WAAW;CACzB;;;;;CAMA,UAAU,WAAkC;EAC1C,OAAO,uBAAuB,KAAK,MAAM,SAAS;CACpD;AACF;;;;;;;;;;;;AAaA,IAAa,6BAAb,cACU,uBAEV;;;;;CAKE,UAAsB;EACpB,OAAQ,KAAK,SAAS,CAAC,CAAsB,QAAQ;CACvD;AACF"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
const require_column_discovered_recipe = require("./column_discovered_recipe.cjs");
|
|
2
2
|
const require_column_filtered_recipe = require("./column_filtered_recipe.cjs");
|
|
3
3
|
const require_column_overrided_recipe = require("./column_overrided_recipe.cjs");
|
|
4
|
-
const
|
|
4
|
+
const require_data_column = require("../data_column.cjs");
|
|
5
5
|
let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common");
|
|
6
6
|
//#region src/columns/column_recipes/index.ts
|
|
7
7
|
/**
|
|
@@ -9,7 +9,7 @@ let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common")
|
|
|
9
9
|
* concrete recipe variant based on the id's encoding and recurses on
|
|
10
10
|
* wrappers' inner `source`:
|
|
11
11
|
*
|
|
12
|
-
* - bare {@link PObjectId} (non-JSON) → `
|
|
12
|
+
* - bare {@link PObjectId} (non-JSON) → `DataColumnRecipe.fromId`
|
|
13
13
|
* - `ColumnDiscoveredKey` → {@link ColumnDiscoveredRecipe}
|
|
14
14
|
* - `ColumnOverriddenKey { source, specOverrides }` → recurse on `source`,
|
|
15
15
|
* then {@link ColumnOverriddenRecipe.wrap}
|
|
@@ -22,7 +22,7 @@ let _milaboratories_pl_model_common = require("@milaboratories/pl-model-common")
|
|
|
22
22
|
*/
|
|
23
23
|
function ColumnRecipeBuild(id, opts = {}) {
|
|
24
24
|
const parsed = (0, _milaboratories_pl_model_common.parseColumnIdSafely)(id);
|
|
25
|
-
if ((0, _milaboratories_pl_model_common.isPObjectKey)(parsed)) return
|
|
25
|
+
if ((0, _milaboratories_pl_model_common.isPObjectKey)(parsed)) return require_data_column.DataColumn.fromId(id, opts);
|
|
26
26
|
if ((0, _milaboratories_pl_model_common.isColumnDiscoveredKey)(parsed)) return require_column_discovered_recipe.ColumnDiscoveredRecipe.fromKey(parsed, opts);
|
|
27
27
|
if ((0, _milaboratories_pl_model_common.isColumnOverriddenKey)(parsed)) {
|
|
28
28
|
const inner = ColumnRecipe(parsed.source, opts);
|
|
@@ -46,27 +46,17 @@ function ColumnRecipeBuild(id, opts = {}) {
|
|
|
46
46
|
*/
|
|
47
47
|
function ColumnRecipeGetStatus(id, opts = {}) {
|
|
48
48
|
const parsed = (0, _milaboratories_pl_model_common.parseColumnIdSafely)(id);
|
|
49
|
-
if ((0, _milaboratories_pl_model_common.isPObjectKey)(parsed)) return
|
|
49
|
+
if ((0, _milaboratories_pl_model_common.isPObjectKey)(parsed)) return require_data_column.DataColumn.getStatusById(id, opts);
|
|
50
50
|
if ((0, _milaboratories_pl_model_common.isColumnDiscoveredKey)(parsed)) return require_column_discovered_recipe.ColumnDiscoveredRecipe.getStatusByKey(parsed, opts);
|
|
51
51
|
if ((0, _milaboratories_pl_model_common.isColumnOverriddenKey)(parsed)) return require_column_overrided_recipe.ColumnOverriddenRecipe.getStatusByKey(parsed, opts);
|
|
52
52
|
if ((0, _milaboratories_pl_model_common.isColumnFilteredKey)(parsed)) return require_column_filtered_recipe.ColumnFilteredRecipe.getStatusByKey(parsed, opts);
|
|
53
53
|
throw new Error(`Unsupported ColumnRecipe id variant: ${id}`);
|
|
54
54
|
}
|
|
55
55
|
const ColumnRecipe = Object.assign(ColumnRecipeBuild, { getStatus: ColumnRecipeGetStatus });
|
|
56
|
-
/**
|
|
57
|
-
* Type-guard for any recipe class — leaf {@link ColumnLazyImpl} or any of the
|
|
58
|
-
* wrapper recipes ({@link ColumnDiscoveredRecipe}, {@link ColumnFilteredRecipe},
|
|
59
|
-
* {@link ColumnOverriddenRecipe}). Use when a value may be a raw id, a `PColumn`,
|
|
60
|
-
* or a recipe and you want to branch on the recipe case.
|
|
61
|
-
*/
|
|
62
|
-
function isColumnRecipe(value) {
|
|
63
|
-
return value instanceof require_column_lazy.ColumnLazyImpl || value instanceof require_column_discovered_recipe.ColumnDiscoveredRecipe || value instanceof require_column_filtered_recipe.ColumnFilteredRecipe || value instanceof require_column_overrided_recipe.ColumnOverriddenRecipe;
|
|
64
|
-
}
|
|
65
56
|
//#endregion
|
|
66
57
|
exports.ColumnDiscoveredRecipe = require_column_discovered_recipe.ColumnDiscoveredRecipe;
|
|
67
58
|
exports.ColumnFilteredRecipe = require_column_filtered_recipe.ColumnFilteredRecipe;
|
|
68
59
|
exports.ColumnOverriddenRecipe = require_column_overrided_recipe.ColumnOverriddenRecipe;
|
|
69
60
|
exports.ColumnRecipe = ColumnRecipe;
|
|
70
|
-
exports.isColumnRecipe = isColumnRecipe;
|
|
71
61
|
|
|
72
62
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.cjs","names":["
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["DataColumn","ColumnDiscoveredRecipe","ColumnOverriddenRecipe","ColumnFilteredRecipe"],"sources":["../../../src/columns/column_recipes/index.ts"],"sourcesContent":["import {\n isColumnDiscoveredKey,\n isColumnOverriddenKey,\n parseColumnIdSafely,\n type ColumnUniversalId,\n type PObjectId,\n isPObjectKey,\n isColumnFilteredKey,\n} from \"@milaboratories/pl-model-common\";\nimport type { GlobalCfgRenderCtx } from \"../../render/internal\";\nimport { DataColumn } from \"../data_column\";\nimport { ColumnDiscoveredRecipe } from \"./column_discovered_recipe\";\nimport { ColumnFilteredRecipe } from \"./column_filtered_recipe\";\nimport { ColumnOverriddenRecipe } from \"./column_overrided_recipe\";\nimport type {\n ColumnRecipe as ColumnRecipeBase,\n ColumnRecipeId,\n ColumnResolutionStatus,\n} from \"./types\";\n\nexport type { ColumnFieldStatus, ColumnRecipeId, ColumnResolutionStatus, SpecQuery } from \"./types\";\nexport { ColumnAbsentError } from \"../data_column\";\nexport { ColumnDiscoveredRecipe } from \"./column_discovered_recipe\";\nexport { ColumnFilteredRecipe } from \"./column_filtered_recipe\";\nexport { ColumnOverriddenRecipe } from \"./column_overrided_recipe\";\n\n// Re-declare the interface locally so the name can merge with the dispatcher\n// value declared below: a single name `ColumnRecipe` resolves to the\n// interface in type position and to the factory function (`Object.assign`d\n// with `.getStatus`) in value position.\n// (Type-only re-exports do not participate in TS declaration merging.)\nexport interface ColumnRecipe<\n ID extends ColumnRecipeId = ColumnRecipeId,\n> extends ColumnRecipeBase<ID> {}\n\n/**\n * Build a `ColumnRecipe` from a stringified id. Dispatches to the matching\n * concrete recipe variant based on the id's encoding and recurses on\n * wrappers' inner `source`:\n *\n * - bare {@link PObjectId} (non-JSON) → `DataColumnRecipe.fromId`\n * - `ColumnDiscoveredKey` → {@link ColumnDiscoveredRecipe}\n * - `ColumnOverriddenKey { source, specOverrides }` → recurse on `source`,\n * then {@link ColumnOverriddenRecipe.wrap}\n * - `ColumnFilteredKey { source, axisFilters }` → recurse on `source`,\n * then {@link ColumnFilteredRecipe.wrap}\n *\n * Returns `undefined` for unsupported variants (e.g. AnchoredPColumnId,\n * which needs an anchor map to resolve) or when a nested source itself\n * cannot be built.\n */\nfunction ColumnRecipeBuild(\n id: ColumnUniversalId,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n): undefined | ColumnRecipe {\n const parsed = parseColumnIdSafely(id);\n\n if (isPObjectKey(parsed)) {\n return DataColumn.fromId(id as PObjectId, opts);\n }\n\n if (isColumnDiscoveredKey(parsed)) {\n return ColumnDiscoveredRecipe.fromKey(parsed, opts);\n }\n\n if (isColumnOverriddenKey(parsed)) {\n const inner = ColumnRecipe(parsed.source, opts);\n if (inner === undefined) return undefined;\n return ColumnOverriddenRecipe.wrap(inner, parsed.specOverrides);\n }\n\n if (isColumnFilteredKey(parsed)) {\n // ColumnFilteredKey.source is a stringified ColumnUniversalId (leaf or\n // any nested wrapper). Legacy `FilteredPColumnId` with an AnchoredPColumnId\n // (object) source is not supported here — guard against it explicitly.\n if (typeof parsed.source !== \"string\") {\n throw new Error(\n `Unsupported ColumnRecipe id variant: filtered column with non-string source (${JSON.stringify(parsed.source)})`,\n );\n }\n const inner = ColumnRecipe(parsed.source, opts);\n if (inner === undefined) return undefined;\n return ColumnFilteredRecipe.wrap(inner, parsed.axisFilters);\n }\n\n throw new Error(`Unsupported ColumnRecipe id variant: ${id}`);\n}\n\n/**\n * Resolution status counterpart to {@link ColumnRecipeBuild}. Dispatches on\n * the parsed id shape to the matching `getStatusBy*` static — never\n * constructs the recipe. Use this at boundaries (resolver, filter/sort\n * targets) to throw early on `absent` instead of silently producing an empty\n * recipe via {@link ColumnRecipeBuild}.\n */\nfunction ColumnRecipeGetStatus(\n id: ColumnUniversalId,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n): ColumnResolutionStatus {\n const parsed = parseColumnIdSafely(id);\n if (isPObjectKey(parsed)) return DataColumn.getStatusById(id as PObjectId, opts);\n if (isColumnDiscoveredKey(parsed)) return ColumnDiscoveredRecipe.getStatusByKey(parsed, opts);\n if (isColumnOverriddenKey(parsed)) return ColumnOverriddenRecipe.getStatusByKey(parsed, opts);\n if (isColumnFilteredKey(parsed)) return ColumnFilteredRecipe.getStatusByKey(parsed, opts);\n throw new Error(`Unsupported ColumnRecipe id variant: ${id}`);\n}\n\nexport const ColumnRecipe: typeof ColumnRecipeBuild & {\n readonly getStatus: typeof ColumnRecipeGetStatus;\n} = Object.assign(ColumnRecipeBuild, {\n getStatus: ColumnRecipeGetStatus,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAmDA,SAAS,kBACP,IACA,OAAqC,CAAC,GACZ;CAC1B,MAAM,UAAA,GAAA,gCAAA,oBAAA,CAA6B,EAAE;CAErC,KAAA,GAAA,gCAAA,aAAA,CAAiB,MAAM,GACrB,OAAOA,oBAAAA,WAAW,OAAO,IAAiB,IAAI;CAGhD,KAAA,GAAA,gCAAA,sBAAA,CAA0B,MAAM,GAC9B,OAAOC,iCAAAA,uBAAuB,QAAQ,QAAQ,IAAI;CAGpD,KAAA,GAAA,gCAAA,sBAAA,CAA0B,MAAM,GAAG;EACjC,MAAM,QAAQ,aAAa,OAAO,QAAQ,IAAI;EAC9C,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;EAChC,OAAOC,gCAAAA,uBAAuB,KAAK,OAAO,OAAO,aAAa;CAChE;CAEA,KAAA,GAAA,gCAAA,oBAAA,CAAwB,MAAM,GAAG;EAI/B,IAAI,OAAO,OAAO,WAAW,UAC3B,MAAM,IAAI,MACR,gFAAgF,KAAK,UAAU,OAAO,MAAM,EAAE,EAChH;EAEF,MAAM,QAAQ,aAAa,OAAO,QAAQ,IAAI;EAC9C,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;EAChC,OAAOC,+BAAAA,qBAAqB,KAAK,OAAO,OAAO,WAAW;CAC5D;CAEA,MAAM,IAAI,MAAM,wCAAwC,IAAI;AAC9D;;;;;;;;AASA,SAAS,sBACP,IACA,OAAqC,CAAC,GACd;CACxB,MAAM,UAAA,GAAA,gCAAA,oBAAA,CAA6B,EAAE;CACrC,KAAA,GAAA,gCAAA,aAAA,CAAiB,MAAM,GAAG,OAAOH,oBAAAA,WAAW,cAAc,IAAiB,IAAI;CAC/E,KAAA,GAAA,gCAAA,sBAAA,CAA0B,MAAM,GAAG,OAAOC,iCAAAA,uBAAuB,eAAe,QAAQ,IAAI;CAC5F,KAAA,GAAA,gCAAA,sBAAA,CAA0B,MAAM,GAAG,OAAOC,gCAAAA,uBAAuB,eAAe,QAAQ,IAAI;CAC5F,KAAA,GAAA,gCAAA,oBAAA,CAAwB,MAAM,GAAG,OAAOC,+BAAAA,qBAAqB,eAAe,QAAQ,IAAI;CACxF,MAAM,IAAI,MAAM,wCAAwC,IAAI;AAC9D;AAEA,MAAa,eAET,OAAO,OAAO,mBAAmB,EACnC,WAAW,sBACb,CAAC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { GlobalCfgRenderCtx } from "../../render/internal.js";
|
|
2
2
|
import { ColumnFieldStatus, ColumnRecipe as ColumnRecipe$1, ColumnRecipeId, ColumnResolutionStatus, SpecQuery as SpecQuery$1 } from "./types.js";
|
|
3
|
-
import { ColumnAbsentError } from "../
|
|
3
|
+
import { ColumnAbsentError } from "../data_column.js";
|
|
4
4
|
import { ColumnDiscoveredRecipe } from "./column_discovered_recipe.js";
|
|
5
5
|
import { ColumnFilteredRecipe } from "./column_filtered_recipe.js";
|
|
6
6
|
import { ColumnOverriddenRecipe } from "./column_overrided_recipe.js";
|
|
@@ -13,7 +13,7 @@ interface ColumnRecipe<ID extends ColumnRecipeId = ColumnRecipeId> extends Colum
|
|
|
13
13
|
* concrete recipe variant based on the id's encoding and recurses on
|
|
14
14
|
* wrappers' inner `source`:
|
|
15
15
|
*
|
|
16
|
-
* - bare {@link PObjectId} (non-JSON) → `
|
|
16
|
+
* - bare {@link PObjectId} (non-JSON) → `DataColumnRecipe.fromId`
|
|
17
17
|
* - `ColumnDiscoveredKey` → {@link ColumnDiscoveredRecipe}
|
|
18
18
|
* - `ColumnOverriddenKey { source, specOverrides }` → recurse on `source`,
|
|
19
19
|
* then {@link ColumnOverriddenRecipe.wrap}
|
|
@@ -40,13 +40,6 @@ declare function ColumnRecipeGetStatus(id: ColumnUniversalId, opts?: {
|
|
|
40
40
|
declare const ColumnRecipe: typeof ColumnRecipeBuild & {
|
|
41
41
|
readonly getStatus: typeof ColumnRecipeGetStatus;
|
|
42
42
|
};
|
|
43
|
-
/**
|
|
44
|
-
* Type-guard for any recipe class — leaf {@link ColumnLazyImpl} or any of the
|
|
45
|
-
* wrapper recipes ({@link ColumnDiscoveredRecipe}, {@link ColumnFilteredRecipe},
|
|
46
|
-
* {@link ColumnOverriddenRecipe}). Use when a value may be a raw id, a `PColumn`,
|
|
47
|
-
* or a recipe and you want to branch on the recipe case.
|
|
48
|
-
*/
|
|
49
|
-
declare function isColumnRecipe(value: unknown): value is ColumnRecipe;
|
|
50
43
|
//#endregion
|
|
51
|
-
export { ColumnDiscoveredRecipe, ColumnFilteredRecipe, ColumnOverriddenRecipe, ColumnRecipe, type ColumnRecipeId, type SpecQuery$1 as SpecQuery
|
|
44
|
+
export { ColumnDiscoveredRecipe, ColumnFilteredRecipe, ColumnOverriddenRecipe, ColumnRecipe, type ColumnRecipeId, type SpecQuery$1 as SpecQuery };
|
|
52
45
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/columns/column_recipes/index.ts"],"mappings":";;;;;;;;;UA+BiB,YAAA,YACJ,cAAA,GAAiB,cAAA,UACpB,cAAA,CAAiB,EAAA;;;;;;;;;;;;;;;AAAE;AAAI;iBAkBxB,iBAAA,CACP,EAAA,EAAI,iBAAA,EACJ,IAAA;EAAQ,GAAA,GAAM,kBAAA;AAAA,gBACD,YAAA;;;;;;;;iBAyCN,qBAAA,CACP,EAAA,EAAI,iBAAA,EACJ,IAAA;EAAQ,GAAA,GAAM,kBAAA;AAAA,IACb,sBAAA;AAAA,cASU,YAAA,SAAqB,iBAAA;EAAA,SACvB,SAAA,SAAkB,qBAAqB;AAAA
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../../src/columns/column_recipes/index.ts"],"mappings":";;;;;;;;;UA+BiB,YAAA,YACJ,cAAA,GAAiB,cAAA,UACpB,cAAA,CAAiB,EAAA;;;;;;;;;;;;;;;AAAE;AAAI;iBAkBxB,iBAAA,CACP,EAAA,EAAI,iBAAA,EACJ,IAAA;EAAQ,GAAA,GAAM,kBAAA;AAAA,gBACD,YAAA;;;;;;;;iBAyCN,qBAAA,CACP,EAAA,EAAI,iBAAA,EACJ,IAAA;EAAQ,GAAA,GAAM,kBAAA;AAAA,IACb,sBAAA;AAAA,cASU,YAAA,SAAqB,iBAAA;EAAA,SACvB,SAAA,SAAkB,qBAAqB;AAAA"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ColumnDiscoveredRecipe } from "./column_discovered_recipe.js";
|
|
2
2
|
import { ColumnFilteredRecipe } from "./column_filtered_recipe.js";
|
|
3
3
|
import { ColumnOverriddenRecipe } from "./column_overrided_recipe.js";
|
|
4
|
-
import {
|
|
4
|
+
import { DataColumn } from "../data_column.js";
|
|
5
5
|
import { isColumnDiscoveredKey, isColumnFilteredKey, isColumnOverriddenKey, isPObjectKey, parseColumnIdSafely } from "@milaboratories/pl-model-common";
|
|
6
6
|
//#region src/columns/column_recipes/index.ts
|
|
7
7
|
/**
|
|
@@ -9,7 +9,7 @@ import { isColumnDiscoveredKey, isColumnFilteredKey, isColumnOverriddenKey, isPO
|
|
|
9
9
|
* concrete recipe variant based on the id's encoding and recurses on
|
|
10
10
|
* wrappers' inner `source`:
|
|
11
11
|
*
|
|
12
|
-
* - bare {@link PObjectId} (non-JSON) → `
|
|
12
|
+
* - bare {@link PObjectId} (non-JSON) → `DataColumnRecipe.fromId`
|
|
13
13
|
* - `ColumnDiscoveredKey` → {@link ColumnDiscoveredRecipe}
|
|
14
14
|
* - `ColumnOverriddenKey { source, specOverrides }` → recurse on `source`,
|
|
15
15
|
* then {@link ColumnOverriddenRecipe.wrap}
|
|
@@ -22,7 +22,7 @@ import { isColumnDiscoveredKey, isColumnFilteredKey, isColumnOverriddenKey, isPO
|
|
|
22
22
|
*/
|
|
23
23
|
function ColumnRecipeBuild(id, opts = {}) {
|
|
24
24
|
const parsed = parseColumnIdSafely(id);
|
|
25
|
-
if (isPObjectKey(parsed)) return
|
|
25
|
+
if (isPObjectKey(parsed)) return DataColumn.fromId(id, opts);
|
|
26
26
|
if (isColumnDiscoveredKey(parsed)) return ColumnDiscoveredRecipe.fromKey(parsed, opts);
|
|
27
27
|
if (isColumnOverriddenKey(parsed)) {
|
|
28
28
|
const inner = ColumnRecipe(parsed.source, opts);
|
|
@@ -46,23 +46,14 @@ function ColumnRecipeBuild(id, opts = {}) {
|
|
|
46
46
|
*/
|
|
47
47
|
function ColumnRecipeGetStatus(id, opts = {}) {
|
|
48
48
|
const parsed = parseColumnIdSafely(id);
|
|
49
|
-
if (isPObjectKey(parsed)) return
|
|
49
|
+
if (isPObjectKey(parsed)) return DataColumn.getStatusById(id, opts);
|
|
50
50
|
if (isColumnDiscoveredKey(parsed)) return ColumnDiscoveredRecipe.getStatusByKey(parsed, opts);
|
|
51
51
|
if (isColumnOverriddenKey(parsed)) return ColumnOverriddenRecipe.getStatusByKey(parsed, opts);
|
|
52
52
|
if (isColumnFilteredKey(parsed)) return ColumnFilteredRecipe.getStatusByKey(parsed, opts);
|
|
53
53
|
throw new Error(`Unsupported ColumnRecipe id variant: ${id}`);
|
|
54
54
|
}
|
|
55
55
|
const ColumnRecipe = Object.assign(ColumnRecipeBuild, { getStatus: ColumnRecipeGetStatus });
|
|
56
|
-
/**
|
|
57
|
-
* Type-guard for any recipe class — leaf {@link ColumnLazyImpl} or any of the
|
|
58
|
-
* wrapper recipes ({@link ColumnDiscoveredRecipe}, {@link ColumnFilteredRecipe},
|
|
59
|
-
* {@link ColumnOverriddenRecipe}). Use when a value may be a raw id, a `PColumn`,
|
|
60
|
-
* or a recipe and you want to branch on the recipe case.
|
|
61
|
-
*/
|
|
62
|
-
function isColumnRecipe(value) {
|
|
63
|
-
return value instanceof ColumnLazyImpl || value instanceof ColumnDiscoveredRecipe || value instanceof ColumnFilteredRecipe || value instanceof ColumnOverriddenRecipe;
|
|
64
|
-
}
|
|
65
56
|
//#endregion
|
|
66
|
-
export { ColumnDiscoveredRecipe, ColumnFilteredRecipe, ColumnOverriddenRecipe, ColumnRecipe
|
|
57
|
+
export { ColumnDiscoveredRecipe, ColumnFilteredRecipe, ColumnOverriddenRecipe, ColumnRecipe };
|
|
67
58
|
|
|
68
59
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../../../src/columns/column_recipes/index.ts"],"sourcesContent":["import {\n isColumnDiscoveredKey,\n isColumnOverriddenKey,\n parseColumnIdSafely,\n type ColumnUniversalId,\n type PObjectId,\n isPObjectKey,\n isColumnFilteredKey,\n} from \"@milaboratories/pl-model-common\";\nimport type { GlobalCfgRenderCtx } from \"../../render/internal\";\nimport {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../../src/columns/column_recipes/index.ts"],"sourcesContent":["import {\n isColumnDiscoveredKey,\n isColumnOverriddenKey,\n parseColumnIdSafely,\n type ColumnUniversalId,\n type PObjectId,\n isPObjectKey,\n isColumnFilteredKey,\n} from \"@milaboratories/pl-model-common\";\nimport type { GlobalCfgRenderCtx } from \"../../render/internal\";\nimport { DataColumn } from \"../data_column\";\nimport { ColumnDiscoveredRecipe } from \"./column_discovered_recipe\";\nimport { ColumnFilteredRecipe } from \"./column_filtered_recipe\";\nimport { ColumnOverriddenRecipe } from \"./column_overrided_recipe\";\nimport type {\n ColumnRecipe as ColumnRecipeBase,\n ColumnRecipeId,\n ColumnResolutionStatus,\n} from \"./types\";\n\nexport type { ColumnFieldStatus, ColumnRecipeId, ColumnResolutionStatus, SpecQuery } from \"./types\";\nexport { ColumnAbsentError } from \"../data_column\";\nexport { ColumnDiscoveredRecipe } from \"./column_discovered_recipe\";\nexport { ColumnFilteredRecipe } from \"./column_filtered_recipe\";\nexport { ColumnOverriddenRecipe } from \"./column_overrided_recipe\";\n\n// Re-declare the interface locally so the name can merge with the dispatcher\n// value declared below: a single name `ColumnRecipe` resolves to the\n// interface in type position and to the factory function (`Object.assign`d\n// with `.getStatus`) in value position.\n// (Type-only re-exports do not participate in TS declaration merging.)\nexport interface ColumnRecipe<\n ID extends ColumnRecipeId = ColumnRecipeId,\n> extends ColumnRecipeBase<ID> {}\n\n/**\n * Build a `ColumnRecipe` from a stringified id. Dispatches to the matching\n * concrete recipe variant based on the id's encoding and recurses on\n * wrappers' inner `source`:\n *\n * - bare {@link PObjectId} (non-JSON) → `DataColumnRecipe.fromId`\n * - `ColumnDiscoveredKey` → {@link ColumnDiscoveredRecipe}\n * - `ColumnOverriddenKey { source, specOverrides }` → recurse on `source`,\n * then {@link ColumnOverriddenRecipe.wrap}\n * - `ColumnFilteredKey { source, axisFilters }` → recurse on `source`,\n * then {@link ColumnFilteredRecipe.wrap}\n *\n * Returns `undefined` for unsupported variants (e.g. AnchoredPColumnId,\n * which needs an anchor map to resolve) or when a nested source itself\n * cannot be built.\n */\nfunction ColumnRecipeBuild(\n id: ColumnUniversalId,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n): undefined | ColumnRecipe {\n const parsed = parseColumnIdSafely(id);\n\n if (isPObjectKey(parsed)) {\n return DataColumn.fromId(id as PObjectId, opts);\n }\n\n if (isColumnDiscoveredKey(parsed)) {\n return ColumnDiscoveredRecipe.fromKey(parsed, opts);\n }\n\n if (isColumnOverriddenKey(parsed)) {\n const inner = ColumnRecipe(parsed.source, opts);\n if (inner === undefined) return undefined;\n return ColumnOverriddenRecipe.wrap(inner, parsed.specOverrides);\n }\n\n if (isColumnFilteredKey(parsed)) {\n // ColumnFilteredKey.source is a stringified ColumnUniversalId (leaf or\n // any nested wrapper). Legacy `FilteredPColumnId` with an AnchoredPColumnId\n // (object) source is not supported here — guard against it explicitly.\n if (typeof parsed.source !== \"string\") {\n throw new Error(\n `Unsupported ColumnRecipe id variant: filtered column with non-string source (${JSON.stringify(parsed.source)})`,\n );\n }\n const inner = ColumnRecipe(parsed.source, opts);\n if (inner === undefined) return undefined;\n return ColumnFilteredRecipe.wrap(inner, parsed.axisFilters);\n }\n\n throw new Error(`Unsupported ColumnRecipe id variant: ${id}`);\n}\n\n/**\n * Resolution status counterpart to {@link ColumnRecipeBuild}. Dispatches on\n * the parsed id shape to the matching `getStatusBy*` static — never\n * constructs the recipe. Use this at boundaries (resolver, filter/sort\n * targets) to throw early on `absent` instead of silently producing an empty\n * recipe via {@link ColumnRecipeBuild}.\n */\nfunction ColumnRecipeGetStatus(\n id: ColumnUniversalId,\n opts: { ctx?: GlobalCfgRenderCtx } = {},\n): ColumnResolutionStatus {\n const parsed = parseColumnIdSafely(id);\n if (isPObjectKey(parsed)) return DataColumn.getStatusById(id as PObjectId, opts);\n if (isColumnDiscoveredKey(parsed)) return ColumnDiscoveredRecipe.getStatusByKey(parsed, opts);\n if (isColumnOverriddenKey(parsed)) return ColumnOverriddenRecipe.getStatusByKey(parsed, opts);\n if (isColumnFilteredKey(parsed)) return ColumnFilteredRecipe.getStatusByKey(parsed, opts);\n throw new Error(`Unsupported ColumnRecipe id variant: ${id}`);\n}\n\nexport const ColumnRecipe: typeof ColumnRecipeBuild & {\n readonly getStatus: typeof ColumnRecipeGetStatus;\n} = Object.assign(ColumnRecipeBuild, {\n getStatus: ColumnRecipeGetStatus,\n});\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AAmDA,SAAS,kBACP,IACA,OAAqC,CAAC,GACZ;CAC1B,MAAM,SAAS,oBAAoB,EAAE;CAErC,IAAI,aAAa,MAAM,GACrB,OAAO,WAAW,OAAO,IAAiB,IAAI;CAGhD,IAAI,sBAAsB,MAAM,GAC9B,OAAO,uBAAuB,QAAQ,QAAQ,IAAI;CAGpD,IAAI,sBAAsB,MAAM,GAAG;EACjC,MAAM,QAAQ,aAAa,OAAO,QAAQ,IAAI;EAC9C,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;EAChC,OAAO,uBAAuB,KAAK,OAAO,OAAO,aAAa;CAChE;CAEA,IAAI,oBAAoB,MAAM,GAAG;EAI/B,IAAI,OAAO,OAAO,WAAW,UAC3B,MAAM,IAAI,MACR,gFAAgF,KAAK,UAAU,OAAO,MAAM,EAAE,EAChH;EAEF,MAAM,QAAQ,aAAa,OAAO,QAAQ,IAAI;EAC9C,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;EAChC,OAAO,qBAAqB,KAAK,OAAO,OAAO,WAAW;CAC5D;CAEA,MAAM,IAAI,MAAM,wCAAwC,IAAI;AAC9D;;;;;;;;AASA,SAAS,sBACP,IACA,OAAqC,CAAC,GACd;CACxB,MAAM,SAAS,oBAAoB,EAAE;CACrC,IAAI,aAAa,MAAM,GAAG,OAAO,WAAW,cAAc,IAAiB,IAAI;CAC/E,IAAI,sBAAsB,MAAM,GAAG,OAAO,uBAAuB,eAAe,QAAQ,IAAI;CAC5F,IAAI,sBAAsB,MAAM,GAAG,OAAO,uBAAuB,eAAe,QAAQ,IAAI;CAC5F,IAAI,oBAAoB,MAAM,GAAG,OAAO,qBAAqB,eAAe,QAAQ,IAAI;CACxF,MAAM,IAAI,MAAM,wCAAwC,IAAI;AAC9D;AAEA,MAAa,eAET,OAAO,OAAO,mBAAmB,EACnC,WAAW,sBACb,CAAC"}
|