@milaboratories/pl-model-common 1.47.3 → 1.48.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (90) hide show
  1. package/dist/bmodel/block_kind_ref.cjs +45 -0
  2. package/dist/bmodel/block_kind_ref.cjs.map +1 -0
  3. package/dist/bmodel/block_kind_ref.d.ts +57 -0
  4. package/dist/bmodel/block_kind_ref.d.ts.map +1 -0
  5. package/dist/bmodel/block_kind_ref.js +43 -0
  6. package/dist/bmodel/block_kind_ref.js.map +1 -0
  7. package/dist/bmodel/container.d.ts +8 -0
  8. package/dist/bmodel/container.d.ts.map +1 -1
  9. package/dist/bmodel/index.cjs +4 -0
  10. package/dist/bmodel/index.d.ts +2 -1
  11. package/dist/bmodel/index.js +2 -1
  12. package/dist/columns/dedup.cjs +1 -1
  13. package/dist/columns/dedup.cjs.map +1 -1
  14. package/dist/columns/dedup.d.ts +1 -1
  15. package/dist/columns/dedup.js +1 -1
  16. package/dist/columns/dedup.js.map +1 -1
  17. package/dist/columns/providers.cjs +1 -1
  18. package/dist/columns/providers.cjs.map +1 -1
  19. package/dist/columns/providers.d.ts +1 -1
  20. package/dist/columns/providers.js +1 -1
  21. package/dist/columns/providers.js.map +1 -1
  22. package/dist/drivers/index.cjs +4 -0
  23. package/dist/drivers/index.d.ts +2 -2
  24. package/dist/drivers/index.js +2 -2
  25. package/dist/drivers/pframe/index.cjs +4 -0
  26. package/dist/drivers/pframe/index.d.ts +2 -2
  27. package/dist/drivers/pframe/index.js +2 -2
  28. package/dist/drivers/pframe/spec/ids.cjs +151 -0
  29. package/dist/drivers/pframe/spec/ids.cjs.map +1 -1
  30. package/dist/drivers/pframe/spec/ids.d.ts +53 -1
  31. package/dist/drivers/pframe/spec/ids.d.ts.map +1 -1
  32. package/dist/drivers/pframe/spec/ids.js +150 -3
  33. package/dist/drivers/pframe/spec/ids.js.map +1 -1
  34. package/dist/drivers/pframe/spec/index.cjs +4 -0
  35. package/dist/drivers/pframe/spec/index.d.ts +2 -2
  36. package/dist/drivers/pframe/spec/index.js +2 -2
  37. package/dist/index.cjs +29 -0
  38. package/dist/index.d.ts +7 -2
  39. package/dist/index.js +8 -2
  40. package/dist/plid.cjs +1 -1
  41. package/dist/plid.cjs.map +1 -1
  42. package/dist/plid.d.ts +3 -2
  43. package/dist/plid.d.ts.map +1 -1
  44. package/dist/plid.js +1 -1
  45. package/dist/plid.js.map +1 -1
  46. package/dist/template/index.cjs +20 -0
  47. package/dist/template/index.d.ts +5 -0
  48. package/dist/template/index.js +5 -0
  49. package/dist/template/kind_selector.cjs +92 -0
  50. package/dist/template/kind_selector.cjs.map +1 -0
  51. package/dist/template/kind_selector.d.ts +80 -0
  52. package/dist/template/kind_selector.d.ts.map +1 -0
  53. package/dist/template/kind_selector.js +87 -0
  54. package/dist/template/kind_selector.js.map +1 -0
  55. package/dist/template/project_template_v1.cjs +231 -0
  56. package/dist/template/project_template_v1.cjs.map +1 -0
  57. package/dist/template/project_template_v1.d.ts +215 -0
  58. package/dist/template/project_template_v1.d.ts.map +1 -0
  59. package/dist/template/project_template_v1.js +225 -0
  60. package/dist/template/project_template_v1.js.map +1 -0
  61. package/dist/template/template_ref_form.cjs +73 -0
  62. package/dist/template/template_ref_form.cjs.map +1 -0
  63. package/dist/template/template_ref_form.d.ts +74 -0
  64. package/dist/template/template_ref_form.d.ts.map +1 -0
  65. package/dist/template/template_ref_form.js +72 -0
  66. package/dist/template/template_ref_form.js.map +1 -0
  67. package/dist/template/template_relocate.cjs +46 -0
  68. package/dist/template/template_relocate.cjs.map +1 -0
  69. package/dist/template/template_relocate.d.ts +32 -0
  70. package/dist/template/template_relocate.d.ts.map +1 -0
  71. package/dist/template/template_relocate.js +46 -0
  72. package/dist/template/template_relocate.js.map +1 -0
  73. package/package.json +5 -5
  74. package/src/bmodel/block_kind_ref.ts +59 -0
  75. package/src/bmodel/container.ts +9 -0
  76. package/src/bmodel/index.ts +1 -0
  77. package/src/columns/dedup.ts +1 -1
  78. package/src/columns/providers.ts +1 -1
  79. package/src/drivers/pframe/spec/ids.test.ts +90 -0
  80. package/src/drivers/pframe/spec/ids.ts +191 -1
  81. package/src/index.ts +1 -0
  82. package/src/plid.ts +5 -5
  83. package/src/template/index.ts +4 -0
  84. package/src/template/kind_selector.ts +126 -0
  85. package/src/template/project_template_v1.test.ts +315 -0
  86. package/src/template/project_template_v1.ts +444 -0
  87. package/src/template/template_ref_form.test.ts +86 -0
  88. package/src/template/template_ref_form.ts +108 -0
  89. package/src/template/template_relocate.test.ts +182 -0
  90. package/src/template/template_relocate.ts +61 -0
@@ -28,6 +28,153 @@ function parseColumnIdSafely(str, fallback = void 0) {
28
28
  return fallback;
29
29
  }
30
30
  }
31
+ /** Whether `value` is any of the five key forms a {@link ColumnUniversalId} serializes. */
32
+ function isColumnUniversalKey(value) {
33
+ return require_spec.isPObjectKey(value) || require_filtered_column.isColumnFilteredKey(value) || require_discovered_column.isColumnDiscoveredKey(value) || require_overridden.isColumnOverriddenKey(value);
34
+ }
35
+ function isColumnUniversalId(value) {
36
+ const key = (0, es_toolkit.isString)(value) ? require_json.parseJsonSafely(value, false) : false;
37
+ return key === false ? false : isColumnUniversalKey(key);
38
+ }
39
+ /**
40
+ * Take a value out of however many `JSON.stringify` passes wrapped it, or `undefined`
41
+ * when `s` is not JSON at all.
42
+ *
43
+ * The one definition of "how a value can be hiding inside a string" — a block id can sit
44
+ * under several layers of escaping, and a walk over object properties reaches none of
45
+ * them. Callers differ in what they do at the bottom (this deliberately says nothing
46
+ * about which values count as identifiers), but they must agree on the mechanics, or
47
+ * "what carries a block id" ends up with two answers that drift.
48
+ *
49
+ * The gate is cheap and does NOT require any marker in the body: a filtered id whose
50
+ * innermost leaf is a {@link LocalPObjectKey} carries no `__isRef`, so demanding one
51
+ * would miss it.
52
+ */
53
+ function peelJsonLayers(s) {
54
+ let current = s;
55
+ let layers = 0;
56
+ for (;;) {
57
+ const c0 = current.charCodeAt(0);
58
+ if (c0 !== 123 && c0 !== 34) return void 0;
59
+ let parsed;
60
+ try {
61
+ parsed = JSON.parse(current);
62
+ } catch {
63
+ return;
64
+ }
65
+ if ((0, es_toolkit.isString)(parsed)) {
66
+ if (parsed.length >= current.length) return void 0;
67
+ current = parsed;
68
+ layers++;
69
+ continue;
70
+ }
71
+ return {
72
+ value: parsed,
73
+ layers
74
+ };
75
+ }
76
+ }
77
+ /**
78
+ * Rewrite every block id buried inside a column id.
79
+ *
80
+ * A {@link GlobalPObjectKey} leaf names its upstream by block id, and the wrapper key forms
81
+ * nest by *string* id rather than by object — so a block id can sit under several layers of
82
+ * JSON escaping, and `queriesQualifications` carries one in a map *key*. A caller that only
83
+ * walks object properties never reaches any of them, which is why moving a column id between
84
+ * projects needs this rather than a generic walk.
85
+ *
86
+ * Recursion re-canonicalizes bottom-up, so every level is canonical afterwards — including
87
+ * the rebuilt `queriesQualifications`, whose keys the canonical form sorts. That is the
88
+ * property a textual rewrite cannot have: redirecting an id that is a map key changes what
89
+ * the sorted order should be, and only rebuilding restores it.
90
+ *
91
+ * Returns the input itself when no block id changed, so a caller mapping ids to themselves
92
+ * gets its value back byte-for-byte and never re-serializes a stored id. Any `string` is
93
+ * accepted for the same reason: a caller sweeping a params object cannot know which of its
94
+ * strings are ids, and one that is not is returned as-is.
95
+ *
96
+ * @param remapBlockId old block id → new block id. Throw from it to reject an id that cannot
97
+ * be mapped.
98
+ */
99
+ function remapColumnIdBlockIds(id, remapBlockId) {
100
+ return ((0, es_toolkit.isString)(id) ? remapIdString(id, remapBlockId) : remapKey(id, remapBlockId)) ?? id;
101
+ }
102
+ /**
103
+ * The string half of {@link remapColumnIdBlockIds}. `undefined` means "nothing to change",
104
+ * which is what keeps an unaffected id from being re-serialized.
105
+ *
106
+ * Escape padding is peeled and put back, so an id that reached params through an extra
107
+ * `JSON.stringify` is rewritten in place and comes back wrapped as it was found. A string
108
+ * that does not peel to a column key is left alone: params hold ordinary strings too.
109
+ */
110
+ function remapIdString(id, remapBlockId) {
111
+ const peeled = peelJsonLayers(id);
112
+ if (peeled === void 0 || !isColumnUniversalKey(peeled.value)) return void 0;
113
+ const remappedKey = remapKey(peeled.value, remapBlockId);
114
+ if (remappedKey === void 0) return void 0;
115
+ let rebuilt = stringifyColumnId(remappedKey);
116
+ for (let layer = 0; layer < peeled.layers; layer++) rebuilt = JSON.stringify(rebuilt);
117
+ return rebuilt;
118
+ }
119
+ /** The key half of {@link remapColumnIdBlockIds}. `undefined` means "nothing to change". */
120
+ function remapKey(key, remapBlockId) {
121
+ if (require_spec.isGlobalPObjectKey(key)) {
122
+ const blockId = remapBlockId(key.blockId);
123
+ return blockId === key.blockId ? void 0 : {
124
+ ...key,
125
+ blockId
126
+ };
127
+ }
128
+ if (require_spec.isLocalPObjectKey(key)) return void 0;
129
+ if (require_filtered_column.isColumnFilteredKey(key)) {
130
+ const source = remapIdString(key.source, remapBlockId);
131
+ return source === void 0 ? void 0 : {
132
+ ...key,
133
+ source
134
+ };
135
+ }
136
+ if (require_overridden.isColumnOverriddenKey(key)) {
137
+ const source = remapIdString(key.source, remapBlockId);
138
+ return source === void 0 ? void 0 : {
139
+ ...key,
140
+ source
141
+ };
142
+ }
143
+ if (require_discovered_column.isColumnDiscoveredKey(key)) return remapDiscoveredKey(key, remapBlockId);
144
+ throw new Error(`remapColumnIdBlockIds: unrecognized column id structure: ${JSON.stringify(key)}`);
145
+ }
146
+ /**
147
+ * Discovered is the only key form carrying more than one nested id: the column it
148
+ * discovered, one per linker hop, and one per entry in `queriesQualifications` — where the
149
+ * id is the map key, not the value.
150
+ */
151
+ function remapDiscoveredKey(key, remapBlockId) {
152
+ const column = remapIdString(key.column, remapBlockId);
153
+ let pathChanged = false;
154
+ const path = key.path?.map((item) => {
155
+ const itemColumn = remapIdString(item.column, remapBlockId);
156
+ if (itemColumn === void 0) return item;
157
+ pathChanged = true;
158
+ return {
159
+ ...item,
160
+ column: itemColumn
161
+ };
162
+ });
163
+ let queriesChanged = false;
164
+ const queriesQualifications = key.queriesQualifications && Object.fromEntries(Object.entries(key.queriesQualifications).map(([queryId, qualifications]) => {
165
+ const remappedId = remapIdString(queryId, remapBlockId);
166
+ if (remappedId === void 0) return [queryId, qualifications];
167
+ queriesChanged = true;
168
+ return [remappedId, qualifications];
169
+ }));
170
+ if (column === void 0 && !pathChanged && !queriesChanged) return void 0;
171
+ return {
172
+ ...key,
173
+ ...column !== void 0 ? { column } : {},
174
+ ...pathChanged ? { path } : {},
175
+ ...queriesChanged ? { queriesQualifications } : {}
176
+ };
177
+ }
31
178
  /**
32
179
  * Walk a rich column id down to its terminal leaf {@link PObjectId}.
33
180
  */
@@ -69,9 +216,13 @@ function reconstructSpecFromId(baseSpec, id) {
69
216
  }
70
217
  //#endregion
71
218
  exports.extractPObjectId = extractPObjectId;
219
+ exports.isColumnUniversalId = isColumnUniversalId;
220
+ exports.isColumnUniversalKey = isColumnUniversalKey;
72
221
  exports.parseColumnId = parseColumnId;
73
222
  exports.parseColumnIdSafely = parseColumnIdSafely;
223
+ exports.peelJsonLayers = peelJsonLayers;
74
224
  exports.reconstructSpecFromId = reconstructSpecFromId;
225
+ exports.remapColumnIdBlockIds = remapColumnIdBlockIds;
75
226
  exports.stringifyColumnId = stringifyColumnId;
76
227
 
77
228
  //# sourceMappingURL=ids.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"ids.cjs","names":["canonicalizeJson","isPObjectId","isPObjectKey","createPObjectId","isColumnFilteredKey","isColumnOverriddenKey","isColumnDiscoveredKey","applyAxisFilters","applySpecOverrides"],"sources":["../../../../src/drivers/pframe/spec/ids.ts"],"sourcesContent":["import type { AnchoredPColumnId } from \"./selectors\";\nimport {\n applyAxisFilters,\n isColumnFilteredKey,\n type ColumnFilteredId,\n type ColumnFilteredKey,\n type FilteredPColumnId,\n} from \"./filtered_column\";\nimport {\n createPObjectId,\n isPObjectId,\n isPObjectKey,\n LocalPObjectKey,\n type GlobalPObjectId,\n type GlobalPObjectKey,\n type LocalPObjectId,\n type PObjectId,\n} from \"../../../pool\";\nimport {\n isColumnDiscoveredKey,\n type ColumnDiscoveredId,\n type ColumnDiscoveredKey,\n} from \"./discovered_column\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport {\n applySpecOverrides,\n isColumnOverriddenKey,\n type ColumnOverriddenId,\n type ColumnOverriddenKey,\n} from \"./overridden\";\nimport { canonicalizeJson } from \"../../../json\";\nimport { AxisSpec, PColumnSpec } from \"./spec\";\nimport { isString } from \"es-toolkit\";\n\n/**\n * Per-axis patches keyed by positional index in the base spec's `axesSpec`.\n *\n * Using position rather than `name` lets us disambiguate linker-style specs\n * that carry multiple axes with the same `name` differentiated by `domain` /\n * `contextDomain` (e.g. a `group`, `group/primary`, `group/secondary` triple).\n *\n * A patch at index `>= base.axesSpec.length` appends a new axis at that slot.\n */\nexport type AxisPatches = Record<number, Partial<AxisSpec>>;\n\n/**\n * Universal column identifier optionally anchored and optionally filtered.\n * @deprecated use {@link ColumnUniversalKey}\n */\nexport type UniversalPColumnId = AnchoredPColumnId | FilteredPColumnId;\n\n/**\n * Canonically serialized {@link UniversalPColumnId}.\n * @deprecated use {@link ColumnUniversalId}\n */\nexport type SUniversalPColumnId = ColumnUniversalId;\n// export type SUniversalPColumnId = Branded<PObjectId, \"SUniversalPColumnId\", \"__pl_model_brand_2__\">;\n\nexport type ColumnUniversalKey =\n | LocalPObjectKey\n | GlobalPObjectKey\n | ColumnFilteredKey\n | ColumnDiscoveredKey\n | ColumnOverriddenKey;\n\nexport type ColumnUniversalId =\n | LocalPObjectId\n | GlobalPObjectId\n | ColumnFilteredId\n | ColumnDiscoveredId\n | ColumnOverriddenId;\n\n/**\n * Canonically serializes a column key to a branded string id. Accepts both\n * the new {@link ColumnUniversalKey} and the deprecated {@link UniversalPColumnId}\n * (anchored / old filtered object form).\n */\nexport function stringifyColumnId(id: ColumnUniversalKey | UniversalPColumnId): ColumnUniversalId {\n return canonicalizeJson(id) as ColumnUniversalId;\n}\n\n/**\n * Parses a canonically serialized column id back to its key form.\n */\nexport function parseColumnId(str: ColumnUniversalId): ColumnUniversalKey {\n return JSON.parse(str) as ColumnUniversalKey;\n}\n\nexport function parseColumnIdSafely(\n str: ColumnUniversalId,\n fallback = undefined,\n): ColumnUniversalKey | typeof fallback {\n try {\n return JSON.parse(str) as ColumnUniversalKey;\n } catch {\n return fallback;\n }\n}\n\n/**\n * Walk a rich column id down to its terminal leaf {@link PObjectId}.\n */\nexport function extractPObjectId(id: ColumnUniversalId | ColumnUniversalKey): PObjectId {\n if (isString(id)) {\n if (isPObjectId(id)) return id;\n\n const parsed =\n parseColumnIdSafely(id) ??\n throwError(`extractPObjectId: id \"${id}\" is not a valid canonical column id`);\n return extractPObjectId(parsed);\n }\n\n if (isPObjectKey(id)) return createPObjectId(id);\n if (isColumnFilteredKey(id)) return extractPObjectId(id.source);\n if (isColumnOverriddenKey(id)) return extractPObjectId(id.source);\n if (isColumnDiscoveredKey(id)) return extractPObjectId(id.column);\n\n throw new Error(`extractPObjectId: unrecognized column id structure: ${JSON.stringify(id)}`);\n}\n\n/**\n * Reconstruct the effective {@link PColumnSpec} for a rich column id by walking\n * the id chain from leaf to outermost wrapper, applying each layer's spec\n * transformation in the same order the corresponding recipe would.\n *\n * Layer semantics:\n * - Leaf ({@link LocalPObjectKey} / {@link GlobalPObjectKey}): no transformation.\n * - {@link ColumnDiscoveredKey}: pass-through, descends into `column`.\n * - {@link ColumnFilteredKey}: drops the axes whose positional index appears in\n * `axisFilters[i][0]` from the inner spec's `axesSpec` — mirrors\n * `ColumnFilteredRecipe.getSpec()`.\n * - {@link ColumnOverriddenKey}: applies `specOverrides` via\n * {@link applySpecOverrides} on top of the inner spec.\n */\nexport function reconstructSpecFromId(\n baseSpec: PColumnSpec,\n id: ColumnUniversalId | ColumnUniversalKey,\n): PColumnSpec {\n if (isString(id)) {\n if (isPObjectId(id)) return baseSpec;\n\n const parsed =\n parseColumnIdSafely(id) ??\n throwError(`reconstructSpecFromId: id \"${id}\" is not a valid canonical column id`);\n return reconstructSpecFromId(baseSpec, parsed);\n }\n\n if (isPObjectKey(id)) return baseSpec;\n if (isColumnDiscoveredKey(id)) return reconstructSpecFromId(baseSpec, id.column);\n if (isColumnFilteredKey(id)) {\n return applyAxisFilters(reconstructSpecFromId(baseSpec, id.source), id.axisFilters);\n }\n if (isColumnOverriddenKey(id)) {\n const inner = reconstructSpecFromId(baseSpec, id.source);\n return applySpecOverrides(inner, id.specOverrides);\n }\n\n throw new Error(`reconstructSpecFromId: unrecognized column id structure: ${JSON.stringify(id)}`);\n}\n"],"mappings":";;;;;;;;;;;;;;AA6EA,SAAgB,kBAAkB,IAAgE;CAChG,OAAOA,aAAAA,iBAAiB,EAAE;AAC5B;;;;AAKA,SAAgB,cAAc,KAA4C;CACxE,OAAO,KAAK,MAAM,GAAG;AACvB;AAEA,SAAgB,oBACd,KACA,WAAW,KAAA,GAC2B;CACtC,IAAI;EACF,OAAO,KAAK,MAAM,GAAG;CACvB,QAAQ;EACN,OAAO;CACT;AACF;;;;AAKA,SAAgB,iBAAiB,IAAuD;CACtF,KAAA,GAAA,WAAA,SAAA,CAAa,EAAE,GAAG;EAChB,IAAIC,aAAAA,YAAY,EAAE,GAAG,OAAO;EAK5B,OAAO,iBAFL,oBAAoB,EAAE,MAAA,GAAA,wBAAA,WAAA,CACX,yBAAyB,GAAG,qCAAqC,CAChD;CAChC;CAEA,IAAIC,aAAAA,aAAa,EAAE,GAAG,OAAOC,aAAAA,gBAAgB,EAAE;CAC/C,IAAIC,wBAAAA,oBAAoB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM;CAC9D,IAAIC,mBAAAA,sBAAsB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM;CAChE,IAAIC,0BAAAA,sBAAsB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM;CAEhE,MAAM,IAAI,MAAM,uDAAuD,KAAK,UAAU,EAAE,GAAG;AAC7F;;;;;;;;;;;;;;;AAgBA,SAAgB,sBACd,UACA,IACa;CACb,KAAA,GAAA,WAAA,SAAA,CAAa,EAAE,GAAG;EAChB,IAAIL,aAAAA,YAAY,EAAE,GAAG,OAAO;EAK5B,OAAO,sBAAsB,UAF3B,oBAAoB,EAAE,MAAA,GAAA,wBAAA,WAAA,CACX,8BAA8B,GAAG,qCAAqC,CACtC;CAC/C;CAEA,IAAIC,aAAAA,aAAa,EAAE,GAAG,OAAO;CAC7B,IAAII,0BAAAA,sBAAsB,EAAE,GAAG,OAAO,sBAAsB,UAAU,GAAG,MAAM;CAC/E,IAAIF,wBAAAA,oBAAoB,EAAE,GACxB,OAAOG,wBAAAA,iBAAiB,sBAAsB,UAAU,GAAG,MAAM,GAAG,GAAG,WAAW;CAEpF,IAAIF,mBAAAA,sBAAsB,EAAE,GAE1B,OAAOG,mBAAAA,mBADO,sBAAsB,UAAU,GAAG,MACnB,GAAG,GAAG,aAAa;CAGnD,MAAM,IAAI,MAAM,4DAA4D,KAAK,UAAU,EAAE,GAAG;AAClG"}
1
+ {"version":3,"file":"ids.cjs","names":["canonicalizeJson","isPObjectKey","isColumnFilteredKey","isColumnDiscoveredKey","isColumnOverriddenKey","parseJsonSafely","isGlobalPObjectKey","isLocalPObjectKey","isPObjectId","createPObjectId","applyAxisFilters","applySpecOverrides"],"sources":["../../../../src/drivers/pframe/spec/ids.ts"],"sourcesContent":["import type { AnchoredPColumnId } from \"./selectors\";\nimport {\n applyAxisFilters,\n isColumnFilteredKey,\n type ColumnFilteredId,\n type ColumnFilteredKey,\n type FilteredPColumnId,\n} from \"./filtered_column\";\nimport {\n createPObjectId,\n isGlobalPObjectKey,\n isLocalPObjectKey,\n isPObjectId,\n isPObjectKey,\n LocalPObjectKey,\n type GlobalPObjectId,\n type GlobalPObjectKey,\n type LocalPObjectId,\n type PObjectId,\n} from \"../../../pool\";\nimport {\n isColumnDiscoveredKey,\n type ColumnDiscoveredId,\n type ColumnDiscoveredKey,\n} from \"./discovered_column\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport {\n applySpecOverrides,\n isColumnOverriddenKey,\n type ColumnOverriddenId,\n type ColumnOverriddenKey,\n} from \"./overridden\";\nimport { canonicalizeJson, parseJsonSafely } from \"../../../json\";\nimport { AxisSpec, PColumnSpec } from \"./spec\";\nimport { isString } from \"es-toolkit\";\n\n/**\n * Per-axis patches keyed by positional index in the base spec's `axesSpec`.\n *\n * Using position rather than `name` lets us disambiguate linker-style specs\n * that carry multiple axes with the same `name` differentiated by `domain` /\n * `contextDomain` (e.g. a `group`, `group/primary`, `group/secondary` triple).\n *\n * A patch at index `>= base.axesSpec.length` appends a new axis at that slot.\n */\nexport type AxisPatches = Record<number, Partial<AxisSpec>>;\n\n/**\n * Universal column identifier optionally anchored and optionally filtered.\n * @deprecated use {@link ColumnUniversalKey}\n */\nexport type UniversalPColumnId = AnchoredPColumnId | FilteredPColumnId;\n\n/**\n * Canonically serialized {@link UniversalPColumnId}.\n * @deprecated use {@link ColumnUniversalId}\n */\nexport type SUniversalPColumnId = ColumnUniversalId;\n// export type SUniversalPColumnId = Branded<PObjectId, \"SUniversalPColumnId\", \"__pl_model_brand_2__\">;\n\nexport type ColumnUniversalKey =\n | LocalPObjectKey\n | GlobalPObjectKey\n | ColumnFilteredKey\n | ColumnDiscoveredKey\n | ColumnOverriddenKey;\n\nexport type ColumnUniversalId =\n | LocalPObjectId\n | GlobalPObjectId\n | ColumnFilteredId\n | ColumnDiscoveredId\n | ColumnOverriddenId;\n\n/**\n * Canonically serializes a column key to a branded string id. Accepts both\n * the new {@link ColumnUniversalKey} and the deprecated {@link UniversalPColumnId}\n * (anchored / old filtered object form).\n */\nexport function stringifyColumnId(id: ColumnUniversalKey | UniversalPColumnId): ColumnUniversalId {\n return canonicalizeJson(id) as ColumnUniversalId;\n}\n\n/**\n * Parses a canonically serialized column id back to its key form.\n */\nexport function parseColumnId(str: ColumnUniversalId): ColumnUniversalKey {\n return JSON.parse(str) as ColumnUniversalKey;\n}\n\nexport function parseColumnIdSafely(\n str: ColumnUniversalId,\n fallback = undefined,\n): ColumnUniversalKey | typeof fallback {\n try {\n return JSON.parse(str) as ColumnUniversalKey;\n } catch {\n return fallback;\n }\n}\n\n/** Whether `value` is any of the five key forms a {@link ColumnUniversalId} serializes. */\nexport function isColumnUniversalKey(value: unknown): value is ColumnUniversalKey {\n return (\n isPObjectKey(value) ||\n isColumnFilteredKey(value) ||\n isColumnDiscoveredKey(value) ||\n isColumnOverriddenKey(value)\n );\n}\n\nexport function isColumnUniversalId(value: unknown): value is ColumnUniversalId {\n const key = isString(value) ? parseJsonSafely(value, false) : false;\n return key === false ? false : isColumnUniversalKey(key);\n}\n\n/**\n * A JSON string with its escape padding taken off, and how many passes that took.\n *\n * `layers` counts the `JSON.stringify` passes *above* the encoded value: a canonical id\n * is `layers: 0`, the same id run through `JSON.stringify` once more is `layers: 1`. Keep\n * it to put the value back the way it was found.\n */\nexport type PeeledJsonLayers = {\n readonly value: unknown;\n readonly layers: number;\n};\n\n/**\n * Take a value out of however many `JSON.stringify` passes wrapped it, or `undefined`\n * when `s` is not JSON at all.\n *\n * The one definition of \"how a value can be hiding inside a string\" — a block id can sit\n * under several layers of escaping, and a walk over object properties reaches none of\n * them. Callers differ in what they do at the bottom (this deliberately says nothing\n * about which values count as identifiers), but they must agree on the mechanics, or\n * \"what carries a block id\" ends up with two answers that drift.\n *\n * The gate is cheap and does NOT require any marker in the body: a filtered id whose\n * innermost leaf is a {@link LocalPObjectKey} carries no `__isRef`, so demanding one\n * would miss it.\n */\nexport function peelJsonLayers(s: string): PeeledJsonLayers | undefined {\n let current = s;\n let layers = 0;\n for (;;) {\n const c0 = current.charCodeAt(0);\n if (c0 !== 0x7b /* { */ && c0 !== 0x22 /* \" */) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(current);\n } catch {\n return undefined;\n }\n // A pass that yielded another string was escape padding, so peel again. The string\n // is strictly shorter each time, which is what bounds the loop.\n if (isString(parsed)) {\n if (parsed.length >= current.length) return undefined;\n current = parsed;\n layers++;\n continue;\n }\n return { value: parsed, layers };\n }\n}\n\n/**\n * Rewrite every block id buried inside a column id.\n *\n * A {@link GlobalPObjectKey} leaf names its upstream by block id, and the wrapper key forms\n * nest by *string* id rather than by object — so a block id can sit under several layers of\n * JSON escaping, and `queriesQualifications` carries one in a map *key*. A caller that only\n * walks object properties never reaches any of them, which is why moving a column id between\n * projects needs this rather than a generic walk.\n *\n * Recursion re-canonicalizes bottom-up, so every level is canonical afterwards — including\n * the rebuilt `queriesQualifications`, whose keys the canonical form sorts. That is the\n * property a textual rewrite cannot have: redirecting an id that is a map key changes what\n * the sorted order should be, and only rebuilding restores it.\n *\n * Returns the input itself when no block id changed, so a caller mapping ids to themselves\n * gets its value back byte-for-byte and never re-serializes a stored id. Any `string` is\n * accepted for the same reason: a caller sweeping a params object cannot know which of its\n * strings are ids, and one that is not is returned as-is.\n *\n * @param remapBlockId old block id → new block id. Throw from it to reject an id that cannot\n * be mapped.\n */\nexport function remapColumnIdBlockIds<T extends string | ColumnUniversalKey>(\n id: T,\n remapBlockId: (blockId: string) => string,\n): T {\n const remapped = isString(id) ? remapIdString(id, remapBlockId) : remapKey(id, remapBlockId);\n return (remapped ?? id) as T;\n}\n\n/**\n * The string half of {@link remapColumnIdBlockIds}. `undefined` means \"nothing to change\",\n * which is what keeps an unaffected id from being re-serialized.\n *\n * Escape padding is peeled and put back, so an id that reached params through an extra\n * `JSON.stringify` is rewritten in place and comes back wrapped as it was found. A string\n * that does not peel to a column key is left alone: params hold ordinary strings too.\n */\nfunction remapIdString(id: string, remapBlockId: (blockId: string) => string): string | undefined {\n const peeled = peelJsonLayers(id);\n if (peeled === undefined || !isColumnUniversalKey(peeled.value)) return undefined;\n\n const remappedKey = remapKey(peeled.value, remapBlockId);\n if (remappedKey === undefined) return undefined;\n\n let rebuilt: string = stringifyColumnId(remappedKey);\n for (let layer = 0; layer < peeled.layers; layer++) rebuilt = JSON.stringify(rebuilt);\n return rebuilt;\n}\n\n/** The key half of {@link remapColumnIdBlockIds}. `undefined` means \"nothing to change\". */\nfunction remapKey(\n key: ColumnUniversalKey,\n remapBlockId: (blockId: string) => string,\n): ColumnUniversalKey | undefined {\n if (isGlobalPObjectKey(key)) {\n const blockId = remapBlockId(key.blockId);\n return blockId === key.blockId ? undefined : { ...key, blockId };\n }\n\n // A local leaf names its column by a path inside its own block — no block id.\n if (isLocalPObjectKey(key)) return undefined;\n\n if (isColumnFilteredKey(key)) {\n const source = remapIdString(key.source, remapBlockId);\n return source === undefined ? undefined : { ...key, source: source as ColumnUniversalId };\n }\n\n if (isColumnOverriddenKey(key)) {\n const source = remapIdString(key.source, remapBlockId);\n // Remapping preserves the id's shape, so `source` is still not an Overridden id.\n return source === undefined\n ? undefined\n : { ...key, source: source as ColumnOverriddenKey[\"source\"] };\n }\n\n if (isColumnDiscoveredKey(key)) return remapDiscoveredKey(key, remapBlockId);\n\n throw new Error(\n `remapColumnIdBlockIds: unrecognized column id structure: ${JSON.stringify(key)}`,\n );\n}\n\n/**\n * Discovered is the only key form carrying more than one nested id: the column it\n * discovered, one per linker hop, and one per entry in `queriesQualifications` — where the\n * id is the map key, not the value.\n */\nfunction remapDiscoveredKey(\n key: ColumnDiscoveredKey,\n remapBlockId: (blockId: string) => string,\n): ColumnDiscoveredKey | undefined {\n const column = remapIdString(key.column, remapBlockId);\n\n let pathChanged = false;\n const path = key.path?.map((item) => {\n const itemColumn = remapIdString(item.column, remapBlockId);\n if (itemColumn === undefined) return item;\n pathChanged = true;\n return { ...item, column: itemColumn as ColumnUniversalId };\n });\n\n let queriesChanged = false;\n const queriesQualifications =\n key.queriesQualifications &&\n (Object.fromEntries(\n Object.entries(key.queriesQualifications).map(([queryId, qualifications]) => {\n const remappedId = remapIdString(queryId, remapBlockId);\n if (remappedId === undefined) return [queryId, qualifications];\n queriesChanged = true;\n return [remappedId, qualifications];\n }),\n ) as ColumnDiscoveredKey[\"queriesQualifications\"]);\n\n if (column === undefined && !pathChanged && !queriesChanged) return undefined;\n return {\n ...key,\n ...(column !== undefined ? { column: column as ColumnUniversalId } : {}),\n ...(pathChanged ? { path } : {}),\n ...(queriesChanged ? { queriesQualifications } : {}),\n };\n}\n\n/**\n * Walk a rich column id down to its terminal leaf {@link PObjectId}.\n */\nexport function extractPObjectId(id: ColumnUniversalId | ColumnUniversalKey): PObjectId {\n if (isString(id)) {\n if (isPObjectId(id)) return id;\n\n const parsed =\n parseColumnIdSafely(id) ??\n throwError(`extractPObjectId: id \"${id}\" is not a valid canonical column id`);\n return extractPObjectId(parsed);\n }\n\n if (isPObjectKey(id)) return createPObjectId(id);\n if (isColumnFilteredKey(id)) return extractPObjectId(id.source);\n if (isColumnOverriddenKey(id)) return extractPObjectId(id.source);\n if (isColumnDiscoveredKey(id)) return extractPObjectId(id.column);\n\n throw new Error(`extractPObjectId: unrecognized column id structure: ${JSON.stringify(id)}`);\n}\n\n/**\n * Reconstruct the effective {@link PColumnSpec} for a rich column id by walking\n * the id chain from leaf to outermost wrapper, applying each layer's spec\n * transformation in the same order the corresponding recipe would.\n *\n * Layer semantics:\n * - Leaf ({@link LocalPObjectKey} / {@link GlobalPObjectKey}): no transformation.\n * - {@link ColumnDiscoveredKey}: pass-through, descends into `column`.\n * - {@link ColumnFilteredKey}: drops the axes whose positional index appears in\n * `axisFilters[i][0]` from the inner spec's `axesSpec` — mirrors\n * `ColumnFilteredRecipe.getSpec()`.\n * - {@link ColumnOverriddenKey}: applies `specOverrides` via\n * {@link applySpecOverrides} on top of the inner spec.\n */\nexport function reconstructSpecFromId(\n baseSpec: PColumnSpec,\n id: ColumnUniversalId | ColumnUniversalKey,\n): PColumnSpec {\n if (isString(id)) {\n if (isPObjectId(id)) return baseSpec;\n\n const parsed =\n parseColumnIdSafely(id) ??\n throwError(`reconstructSpecFromId: id \"${id}\" is not a valid canonical column id`);\n return reconstructSpecFromId(baseSpec, parsed);\n }\n\n if (isPObjectKey(id)) return baseSpec;\n if (isColumnDiscoveredKey(id)) return reconstructSpecFromId(baseSpec, id.column);\n if (isColumnFilteredKey(id)) {\n return applyAxisFilters(reconstructSpecFromId(baseSpec, id.source), id.axisFilters);\n }\n if (isColumnOverriddenKey(id)) {\n const inner = reconstructSpecFromId(baseSpec, id.source);\n return applySpecOverrides(inner, id.specOverrides);\n }\n\n throw new Error(`reconstructSpecFromId: unrecognized column id structure: ${JSON.stringify(id)}`);\n}\n"],"mappings":";;;;;;;;;;;;;;AA+EA,SAAgB,kBAAkB,IAAgE;CAChG,OAAOA,aAAAA,iBAAiB,EAAE;AAC5B;;;;AAKA,SAAgB,cAAc,KAA4C;CACxE,OAAO,KAAK,MAAM,GAAG;AACvB;AAEA,SAAgB,oBACd,KACA,WAAW,KAAA,GAC2B;CACtC,IAAI;EACF,OAAO,KAAK,MAAM,GAAG;CACvB,QAAQ;EACN,OAAO;CACT;AACF;;AAGA,SAAgB,qBAAqB,OAA6C;CAChF,OACEC,aAAAA,aAAa,KAAK,KAClBC,wBAAAA,oBAAoB,KAAK,KACzBC,0BAAAA,sBAAsB,KAAK,KAC3BC,mBAAAA,sBAAsB,KAAK;AAE/B;AAEA,SAAgB,oBAAoB,OAA4C;CAC9E,MAAM,OAAA,GAAA,WAAA,SAAA,CAAe,KAAK,IAAIC,aAAAA,gBAAgB,OAAO,KAAK,IAAI;CAC9D,OAAO,QAAQ,QAAQ,QAAQ,qBAAqB,GAAG;AACzD;;;;;;;;;;;;;;;AA4BA,SAAgB,eAAe,GAAyC;CACtE,IAAI,UAAU;CACd,IAAI,SAAS;CACb,SAAS;EACP,MAAM,KAAK,QAAQ,WAAW,CAAC;EAC/B,IAAI,OAAO,OAAgB,OAAO,IAAc,OAAO,KAAA;EACvD,IAAI;EACJ,IAAI;GACF,SAAS,KAAK,MAAM,OAAO;EAC7B,QAAQ;GACN;EACF;EAGA,KAAA,GAAA,WAAA,SAAA,CAAa,MAAM,GAAG;GACpB,IAAI,OAAO,UAAU,QAAQ,QAAQ,OAAO,KAAA;GAC5C,UAAU;GACV;GACA;EACF;EACA,OAAO;GAAE,OAAO;GAAQ;EAAO;CACjC;AACF;;;;;;;;;;;;;;;;;;;;;;;AAwBA,SAAgB,sBACd,IACA,cACG;CAEH,SAAA,GAAA,WAAA,SAAA,CAD0B,EAAE,IAAI,cAAc,IAAI,YAAY,IAAI,SAAS,IAAI,YAAY,MACvE;AACtB;;;;;;;;;AAUA,SAAS,cAAc,IAAY,cAA+D;CAChG,MAAM,SAAS,eAAe,EAAE;CAChC,IAAI,WAAW,KAAA,KAAa,CAAC,qBAAqB,OAAO,KAAK,GAAG,OAAO,KAAA;CAExE,MAAM,cAAc,SAAS,OAAO,OAAO,YAAY;CACvD,IAAI,gBAAgB,KAAA,GAAW,OAAO,KAAA;CAEtC,IAAI,UAAkB,kBAAkB,WAAW;CACnD,KAAK,IAAI,QAAQ,GAAG,QAAQ,OAAO,QAAQ,SAAS,UAAU,KAAK,UAAU,OAAO;CACpF,OAAO;AACT;;AAGA,SAAS,SACP,KACA,cACgC;CAChC,IAAIC,aAAAA,mBAAmB,GAAG,GAAG;EAC3B,MAAM,UAAU,aAAa,IAAI,OAAO;EACxC,OAAO,YAAY,IAAI,UAAU,KAAA,IAAY;GAAE,GAAG;GAAK;EAAQ;CACjE;CAGA,IAAIC,aAAAA,kBAAkB,GAAG,GAAG,OAAO,KAAA;CAEnC,IAAIL,wBAAAA,oBAAoB,GAAG,GAAG;EAC5B,MAAM,SAAS,cAAc,IAAI,QAAQ,YAAY;EACrD,OAAO,WAAW,KAAA,IAAY,KAAA,IAAY;GAAE,GAAG;GAAa;EAA4B;CAC1F;CAEA,IAAIE,mBAAAA,sBAAsB,GAAG,GAAG;EAC9B,MAAM,SAAS,cAAc,IAAI,QAAQ,YAAY;EAErD,OAAO,WAAW,KAAA,IACd,KAAA,IACA;GAAE,GAAG;GAAa;EAAwC;CAChE;CAEA,IAAID,0BAAAA,sBAAsB,GAAG,GAAG,OAAO,mBAAmB,KAAK,YAAY;CAE3E,MAAM,IAAI,MACR,4DAA4D,KAAK,UAAU,GAAG,GAChF;AACF;;;;;;AAOA,SAAS,mBACP,KACA,cACiC;CACjC,MAAM,SAAS,cAAc,IAAI,QAAQ,YAAY;CAErD,IAAI,cAAc;CAClB,MAAM,OAAO,IAAI,MAAM,KAAK,SAAS;EACnC,MAAM,aAAa,cAAc,KAAK,QAAQ,YAAY;EAC1D,IAAI,eAAe,KAAA,GAAW,OAAO;EACrC,cAAc;EACd,OAAO;GAAE,GAAG;GAAM,QAAQ;EAAgC;CAC5D,CAAC;CAED,IAAI,iBAAiB;CACrB,MAAM,wBACJ,IAAI,yBACH,OAAO,YACN,OAAO,QAAQ,IAAI,qBAAqB,CAAC,CAAC,KAAK,CAAC,SAAS,oBAAoB;EAC3E,MAAM,aAAa,cAAc,SAAS,YAAY;EACtD,IAAI,eAAe,KAAA,GAAW,OAAO,CAAC,SAAS,cAAc;EAC7D,iBAAiB;EACjB,OAAO,CAAC,YAAY,cAAc;CACpC,CAAC,CACH;CAEF,IAAI,WAAW,KAAA,KAAa,CAAC,eAAe,CAAC,gBAAgB,OAAO,KAAA;CACpE,OAAO;EACL,GAAG;EACH,GAAI,WAAW,KAAA,IAAY,EAAU,OAA4B,IAAI,CAAC;EACtE,GAAI,cAAc,EAAE,KAAK,IAAI,CAAC;EAC9B,GAAI,iBAAiB,EAAE,sBAAsB,IAAI,CAAC;CACpD;AACF;;;;AAKA,SAAgB,iBAAiB,IAAuD;CACtF,KAAA,GAAA,WAAA,SAAA,CAAa,EAAE,GAAG;EAChB,IAAIK,aAAAA,YAAY,EAAE,GAAG,OAAO;EAK5B,OAAO,iBAFL,oBAAoB,EAAE,MAAA,GAAA,wBAAA,WAAA,CACX,yBAAyB,GAAG,qCAAqC,CAChD;CAChC;CAEA,IAAIP,aAAAA,aAAa,EAAE,GAAG,OAAOQ,aAAAA,gBAAgB,EAAE;CAC/C,IAAIP,wBAAAA,oBAAoB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM;CAC9D,IAAIE,mBAAAA,sBAAsB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM;CAChE,IAAID,0BAAAA,sBAAsB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM;CAEhE,MAAM,IAAI,MAAM,uDAAuD,KAAK,UAAU,EAAE,GAAG;AAC7F;;;;;;;;;;;;;;;AAgBA,SAAgB,sBACd,UACA,IACa;CACb,KAAA,GAAA,WAAA,SAAA,CAAa,EAAE,GAAG;EAChB,IAAIK,aAAAA,YAAY,EAAE,GAAG,OAAO;EAK5B,OAAO,sBAAsB,UAF3B,oBAAoB,EAAE,MAAA,GAAA,wBAAA,WAAA,CACX,8BAA8B,GAAG,qCAAqC,CACtC;CAC/C;CAEA,IAAIP,aAAAA,aAAa,EAAE,GAAG,OAAO;CAC7B,IAAIE,0BAAAA,sBAAsB,EAAE,GAAG,OAAO,sBAAsB,UAAU,GAAG,MAAM;CAC/E,IAAID,wBAAAA,oBAAoB,EAAE,GACxB,OAAOQ,wBAAAA,iBAAiB,sBAAsB,UAAU,GAAG,MAAM,GAAG,GAAG,WAAW;CAEpF,IAAIN,mBAAAA,sBAAsB,EAAE,GAE1B,OAAOO,mBAAAA,mBADO,sBAAsB,UAAU,GAAG,MACnB,GAAG,GAAG,aAAa;CAGnD,MAAM,IAAI,MAAM,4DAA4D,KAAK,UAAU,EAAE,GAAG;AAClG"}
@@ -38,6 +38,58 @@ declare function stringifyColumnId(id: ColumnUniversalKey | UniversalPColumnId):
38
38
  */
39
39
  declare function parseColumnId(str: ColumnUniversalId): ColumnUniversalKey;
40
40
  declare function parseColumnIdSafely(str: ColumnUniversalId, fallback?: undefined): ColumnUniversalKey | typeof fallback;
41
+ /** Whether `value` is any of the five key forms a {@link ColumnUniversalId} serializes. */
42
+ declare function isColumnUniversalKey(value: unknown): value is ColumnUniversalKey;
43
+ declare function isColumnUniversalId(value: unknown): value is ColumnUniversalId;
44
+ /**
45
+ * A JSON string with its escape padding taken off, and how many passes that took.
46
+ *
47
+ * `layers` counts the `JSON.stringify` passes *above* the encoded value: a canonical id
48
+ * is `layers: 0`, the same id run through `JSON.stringify` once more is `layers: 1`. Keep
49
+ * it to put the value back the way it was found.
50
+ */
51
+ type PeeledJsonLayers = {
52
+ readonly value: unknown;
53
+ readonly layers: number;
54
+ };
55
+ /**
56
+ * Take a value out of however many `JSON.stringify` passes wrapped it, or `undefined`
57
+ * when `s` is not JSON at all.
58
+ *
59
+ * The one definition of "how a value can be hiding inside a string" — a block id can sit
60
+ * under several layers of escaping, and a walk over object properties reaches none of
61
+ * them. Callers differ in what they do at the bottom (this deliberately says nothing
62
+ * about which values count as identifiers), but they must agree on the mechanics, or
63
+ * "what carries a block id" ends up with two answers that drift.
64
+ *
65
+ * The gate is cheap and does NOT require any marker in the body: a filtered id whose
66
+ * innermost leaf is a {@link LocalPObjectKey} carries no `__isRef`, so demanding one
67
+ * would miss it.
68
+ */
69
+ declare function peelJsonLayers(s: string): PeeledJsonLayers | undefined;
70
+ /**
71
+ * Rewrite every block id buried inside a column id.
72
+ *
73
+ * A {@link GlobalPObjectKey} leaf names its upstream by block id, and the wrapper key forms
74
+ * nest by *string* id rather than by object — so a block id can sit under several layers of
75
+ * JSON escaping, and `queriesQualifications` carries one in a map *key*. A caller that only
76
+ * walks object properties never reaches any of them, which is why moving a column id between
77
+ * projects needs this rather than a generic walk.
78
+ *
79
+ * Recursion re-canonicalizes bottom-up, so every level is canonical afterwards — including
80
+ * the rebuilt `queriesQualifications`, whose keys the canonical form sorts. That is the
81
+ * property a textual rewrite cannot have: redirecting an id that is a map key changes what
82
+ * the sorted order should be, and only rebuilding restores it.
83
+ *
84
+ * Returns the input itself when no block id changed, so a caller mapping ids to themselves
85
+ * gets its value back byte-for-byte and never re-serializes a stored id. Any `string` is
86
+ * accepted for the same reason: a caller sweeping a params object cannot know which of its
87
+ * strings are ids, and one that is not is returned as-is.
88
+ *
89
+ * @param remapBlockId old block id → new block id. Throw from it to reject an id that cannot
90
+ * be mapped.
91
+ */
92
+ declare function remapColumnIdBlockIds<T extends string | ColumnUniversalKey>(id: T, remapBlockId: (blockId: string) => string): T;
41
93
  /**
42
94
  * Walk a rich column id down to its terminal leaf {@link PObjectId}.
43
95
  */
@@ -58,5 +110,5 @@ declare function extractPObjectId(id: ColumnUniversalId | ColumnUniversalKey): P
58
110
  */
59
111
  declare function reconstructSpecFromId(baseSpec: PColumnSpec, id: ColumnUniversalId | ColumnUniversalKey): PColumnSpec;
60
112
  //#endregion
61
- export { AxisPatches, ColumnUniversalId, ColumnUniversalKey, SUniversalPColumnId, UniversalPColumnId, extractPObjectId, parseColumnId, parseColumnIdSafely, reconstructSpecFromId, stringifyColumnId };
113
+ export { AxisPatches, ColumnUniversalId, ColumnUniversalKey, PeeledJsonLayers, SUniversalPColumnId, UniversalPColumnId, extractPObjectId, isColumnUniversalId, isColumnUniversalKey, parseColumnId, parseColumnIdSafely, peelJsonLayers, reconstructSpecFromId, remapColumnIdBlockIds, stringifyColumnId };
62
114
  //# sourceMappingURL=ids.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ids.d.ts","names":[],"sources":["../../../../src/drivers/pframe/spec/ids.ts"],"mappings":";;;;;;;;;;AA2CA;;;;;;KAAY,WAAA,GAAc,MAAA,SAAe,OAAA,CAAQ,QAAA;;;;;KAMrC,kBAAA,GAAqB,iBAAA,GAAoB,iBAAiB;AANb;AAMzD;;;AANyD,KAY7C,mBAAA,GAAsB,iBAAiB;AAAA,KAGvC,kBAAA,GACR,eAAA,GACA,gBAAA,GACA,iBAAA,GACA,mBAAA,GACA,mBAAA;AAAA,KAEQ,iBAAA,GACR,cAAA,GACA,eAAA,GACA,gBAAA,GACA,kBAAA,GACA,kBAAA;;;;AAf+C;AAGnD;iBAmBgB,iBAAA,CAAkB,EAAA,EAAI,kBAAA,GAAqB,kBAAA,GAAqB,iBAAA;;;;iBAOhE,aAAA,CAAc,GAAA,EAAK,iBAAA,GAAoB,kBAAkB;AAAA,iBAIzD,mBAAA,CACd,GAAA,EAAK,iBAAA,EACL,QAAA,eACC,kBAAA,UAA4B,QAAA;;;;iBAWf,gBAAA,CAAiB,EAAA,EAAI,iBAAA,GAAoB,kBAAA,GAAqB,SAAA;;;;;;AAvCvD;AAEvB;;;;;;;;iBAqEgB,qBAAA,CACd,QAAA,EAAU,WAAA,EACV,EAAA,EAAI,iBAAA,GAAoB,kBAAA,GACvB,WAAA"}
1
+ {"version":3,"file":"ids.d.ts","names":[],"sources":["../../../../src/drivers/pframe/spec/ids.ts"],"mappings":";;;;;;;;;;AA6CA;;;;;;KAAY,WAAA,GAAc,MAAA,SAAe,OAAA,CAAQ,QAAA;;;;;KAMrC,kBAAA,GAAqB,iBAAA,GAAoB,iBAAiB;AANb;AAMzD;;;AANyD,KAY7C,mBAAA,GAAsB,iBAAiB;AAAA,KAGvC,kBAAA,GACR,eAAA,GACA,gBAAA,GACA,iBAAA,GACA,mBAAA,GACA,mBAAA;AAAA,KAEQ,iBAAA,GACR,cAAA,GACA,eAAA,GACA,gBAAA,GACA,kBAAA,GACA,kBAAA;;;;AAf+C;AAGnD;iBAmBgB,iBAAA,CAAkB,EAAA,EAAI,kBAAA,GAAqB,kBAAA,GAAqB,iBAAA;;;;iBAOhE,aAAA,CAAc,GAAA,EAAK,iBAAA,GAAoB,kBAAkB;AAAA,iBAIzD,mBAAA,CACd,GAAA,EAAK,iBAAA,EACL,QAAA,eACC,kBAAA,UAA4B,QAAA;;iBASf,oBAAA,CAAqB,KAAA,YAAiB,KAAA,IAAS,kBAAkB;AAAA,iBASjE,mBAAA,CAAoB,KAAA,YAAiB,KAAA,IAAS,iBAAiB;;;;;;;AA9CxD;KA0DX,gBAAA;EAAA,SACD,KAAA;EAAA,SACA,MAAM;AAAA;;;;;;;;;;;;;AArDK;AAOtB;iBA+DgB,cAAA,CAAe,CAAA,WAAY,gBAAgB;;;;;;;;;;;;AA/DsC;AAOjG;;;;;;;;AAAyE;AAIzE;iBAkGgB,qBAAA,oBAAyC,kBAAA,EACvD,EAAA,EAAI,CAAA,EACJ,YAAA,GAAe,OAAA,sBACd,CAAA;;;;iBAqGa,gBAAA,CAAiB,EAAA,EAAI,iBAAA,GAAoB,kBAAA,GAAqB,SAAA;;;;;;;;;AAvMvC;AASvC;;;;;iBA8NgB,qBAAA,CACd,QAAA,EAAU,WAAA,EACV,EAAA,EAAI,iBAAA,GAAoB,kBAAA,GACvB,WAAA"}
@@ -1,6 +1,6 @@
1
- import { canonicalizeJson } from "../../../json.js";
1
+ import { canonicalizeJson, parseJsonSafely } from "../../../json.js";
2
2
  import { applyAxisFilters, isColumnFilteredKey } from "./filtered_column.js";
3
- import { createPObjectId, isPObjectId, isPObjectKey } from "../../../pool/spec.js";
3
+ import { createPObjectId, isGlobalPObjectKey, isLocalPObjectKey, isPObjectId, isPObjectKey } from "../../../pool/spec.js";
4
4
  import "../../../pool/index.js";
5
5
  import { isColumnDiscoveredKey } from "./discovered_column.js";
6
6
  import { applySpecOverrides, isColumnOverriddenKey } from "./overridden.js";
@@ -28,6 +28,153 @@ function parseColumnIdSafely(str, fallback = void 0) {
28
28
  return fallback;
29
29
  }
30
30
  }
31
+ /** Whether `value` is any of the five key forms a {@link ColumnUniversalId} serializes. */
32
+ function isColumnUniversalKey(value) {
33
+ return isPObjectKey(value) || isColumnFilteredKey(value) || isColumnDiscoveredKey(value) || isColumnOverriddenKey(value);
34
+ }
35
+ function isColumnUniversalId(value) {
36
+ const key = isString(value) ? parseJsonSafely(value, false) : false;
37
+ return key === false ? false : isColumnUniversalKey(key);
38
+ }
39
+ /**
40
+ * Take a value out of however many `JSON.stringify` passes wrapped it, or `undefined`
41
+ * when `s` is not JSON at all.
42
+ *
43
+ * The one definition of "how a value can be hiding inside a string" — a block id can sit
44
+ * under several layers of escaping, and a walk over object properties reaches none of
45
+ * them. Callers differ in what they do at the bottom (this deliberately says nothing
46
+ * about which values count as identifiers), but they must agree on the mechanics, or
47
+ * "what carries a block id" ends up with two answers that drift.
48
+ *
49
+ * The gate is cheap and does NOT require any marker in the body: a filtered id whose
50
+ * innermost leaf is a {@link LocalPObjectKey} carries no `__isRef`, so demanding one
51
+ * would miss it.
52
+ */
53
+ function peelJsonLayers(s) {
54
+ let current = s;
55
+ let layers = 0;
56
+ for (;;) {
57
+ const c0 = current.charCodeAt(0);
58
+ if (c0 !== 123 && c0 !== 34) return void 0;
59
+ let parsed;
60
+ try {
61
+ parsed = JSON.parse(current);
62
+ } catch {
63
+ return;
64
+ }
65
+ if (isString(parsed)) {
66
+ if (parsed.length >= current.length) return void 0;
67
+ current = parsed;
68
+ layers++;
69
+ continue;
70
+ }
71
+ return {
72
+ value: parsed,
73
+ layers
74
+ };
75
+ }
76
+ }
77
+ /**
78
+ * Rewrite every block id buried inside a column id.
79
+ *
80
+ * A {@link GlobalPObjectKey} leaf names its upstream by block id, and the wrapper key forms
81
+ * nest by *string* id rather than by object — so a block id can sit under several layers of
82
+ * JSON escaping, and `queriesQualifications` carries one in a map *key*. A caller that only
83
+ * walks object properties never reaches any of them, which is why moving a column id between
84
+ * projects needs this rather than a generic walk.
85
+ *
86
+ * Recursion re-canonicalizes bottom-up, so every level is canonical afterwards — including
87
+ * the rebuilt `queriesQualifications`, whose keys the canonical form sorts. That is the
88
+ * property a textual rewrite cannot have: redirecting an id that is a map key changes what
89
+ * the sorted order should be, and only rebuilding restores it.
90
+ *
91
+ * Returns the input itself when no block id changed, so a caller mapping ids to themselves
92
+ * gets its value back byte-for-byte and never re-serializes a stored id. Any `string` is
93
+ * accepted for the same reason: a caller sweeping a params object cannot know which of its
94
+ * strings are ids, and one that is not is returned as-is.
95
+ *
96
+ * @param remapBlockId old block id → new block id. Throw from it to reject an id that cannot
97
+ * be mapped.
98
+ */
99
+ function remapColumnIdBlockIds(id, remapBlockId) {
100
+ return (isString(id) ? remapIdString(id, remapBlockId) : remapKey(id, remapBlockId)) ?? id;
101
+ }
102
+ /**
103
+ * The string half of {@link remapColumnIdBlockIds}. `undefined` means "nothing to change",
104
+ * which is what keeps an unaffected id from being re-serialized.
105
+ *
106
+ * Escape padding is peeled and put back, so an id that reached params through an extra
107
+ * `JSON.stringify` is rewritten in place and comes back wrapped as it was found. A string
108
+ * that does not peel to a column key is left alone: params hold ordinary strings too.
109
+ */
110
+ function remapIdString(id, remapBlockId) {
111
+ const peeled = peelJsonLayers(id);
112
+ if (peeled === void 0 || !isColumnUniversalKey(peeled.value)) return void 0;
113
+ const remappedKey = remapKey(peeled.value, remapBlockId);
114
+ if (remappedKey === void 0) return void 0;
115
+ let rebuilt = stringifyColumnId(remappedKey);
116
+ for (let layer = 0; layer < peeled.layers; layer++) rebuilt = JSON.stringify(rebuilt);
117
+ return rebuilt;
118
+ }
119
+ /** The key half of {@link remapColumnIdBlockIds}. `undefined` means "nothing to change". */
120
+ function remapKey(key, remapBlockId) {
121
+ if (isGlobalPObjectKey(key)) {
122
+ const blockId = remapBlockId(key.blockId);
123
+ return blockId === key.blockId ? void 0 : {
124
+ ...key,
125
+ blockId
126
+ };
127
+ }
128
+ if (isLocalPObjectKey(key)) return void 0;
129
+ if (isColumnFilteredKey(key)) {
130
+ const source = remapIdString(key.source, remapBlockId);
131
+ return source === void 0 ? void 0 : {
132
+ ...key,
133
+ source
134
+ };
135
+ }
136
+ if (isColumnOverriddenKey(key)) {
137
+ const source = remapIdString(key.source, remapBlockId);
138
+ return source === void 0 ? void 0 : {
139
+ ...key,
140
+ source
141
+ };
142
+ }
143
+ if (isColumnDiscoveredKey(key)) return remapDiscoveredKey(key, remapBlockId);
144
+ throw new Error(`remapColumnIdBlockIds: unrecognized column id structure: ${JSON.stringify(key)}`);
145
+ }
146
+ /**
147
+ * Discovered is the only key form carrying more than one nested id: the column it
148
+ * discovered, one per linker hop, and one per entry in `queriesQualifications` — where the
149
+ * id is the map key, not the value.
150
+ */
151
+ function remapDiscoveredKey(key, remapBlockId) {
152
+ const column = remapIdString(key.column, remapBlockId);
153
+ let pathChanged = false;
154
+ const path = key.path?.map((item) => {
155
+ const itemColumn = remapIdString(item.column, remapBlockId);
156
+ if (itemColumn === void 0) return item;
157
+ pathChanged = true;
158
+ return {
159
+ ...item,
160
+ column: itemColumn
161
+ };
162
+ });
163
+ let queriesChanged = false;
164
+ const queriesQualifications = key.queriesQualifications && Object.fromEntries(Object.entries(key.queriesQualifications).map(([queryId, qualifications]) => {
165
+ const remappedId = remapIdString(queryId, remapBlockId);
166
+ if (remappedId === void 0) return [queryId, qualifications];
167
+ queriesChanged = true;
168
+ return [remappedId, qualifications];
169
+ }));
170
+ if (column === void 0 && !pathChanged && !queriesChanged) return void 0;
171
+ return {
172
+ ...key,
173
+ ...column !== void 0 ? { column } : {},
174
+ ...pathChanged ? { path } : {},
175
+ ...queriesChanged ? { queriesQualifications } : {}
176
+ };
177
+ }
31
178
  /**
32
179
  * Walk a rich column id down to its terminal leaf {@link PObjectId}.
33
180
  */
@@ -68,6 +215,6 @@ function reconstructSpecFromId(baseSpec, id) {
68
215
  throw new Error(`reconstructSpecFromId: unrecognized column id structure: ${JSON.stringify(id)}`);
69
216
  }
70
217
  //#endregion
71
- export { extractPObjectId, parseColumnId, parseColumnIdSafely, reconstructSpecFromId, stringifyColumnId };
218
+ export { extractPObjectId, isColumnUniversalId, isColumnUniversalKey, parseColumnId, parseColumnIdSafely, peelJsonLayers, reconstructSpecFromId, remapColumnIdBlockIds, stringifyColumnId };
72
219
 
73
220
  //# sourceMappingURL=ids.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ids.js","names":[],"sources":["../../../../src/drivers/pframe/spec/ids.ts"],"sourcesContent":["import type { AnchoredPColumnId } from \"./selectors\";\nimport {\n applyAxisFilters,\n isColumnFilteredKey,\n type ColumnFilteredId,\n type ColumnFilteredKey,\n type FilteredPColumnId,\n} from \"./filtered_column\";\nimport {\n createPObjectId,\n isPObjectId,\n isPObjectKey,\n LocalPObjectKey,\n type GlobalPObjectId,\n type GlobalPObjectKey,\n type LocalPObjectId,\n type PObjectId,\n} from \"../../../pool\";\nimport {\n isColumnDiscoveredKey,\n type ColumnDiscoveredId,\n type ColumnDiscoveredKey,\n} from \"./discovered_column\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport {\n applySpecOverrides,\n isColumnOverriddenKey,\n type ColumnOverriddenId,\n type ColumnOverriddenKey,\n} from \"./overridden\";\nimport { canonicalizeJson } from \"../../../json\";\nimport { AxisSpec, PColumnSpec } from \"./spec\";\nimport { isString } from \"es-toolkit\";\n\n/**\n * Per-axis patches keyed by positional index in the base spec's `axesSpec`.\n *\n * Using position rather than `name` lets us disambiguate linker-style specs\n * that carry multiple axes with the same `name` differentiated by `domain` /\n * `contextDomain` (e.g. a `group`, `group/primary`, `group/secondary` triple).\n *\n * A patch at index `>= base.axesSpec.length` appends a new axis at that slot.\n */\nexport type AxisPatches = Record<number, Partial<AxisSpec>>;\n\n/**\n * Universal column identifier optionally anchored and optionally filtered.\n * @deprecated use {@link ColumnUniversalKey}\n */\nexport type UniversalPColumnId = AnchoredPColumnId | FilteredPColumnId;\n\n/**\n * Canonically serialized {@link UniversalPColumnId}.\n * @deprecated use {@link ColumnUniversalId}\n */\nexport type SUniversalPColumnId = ColumnUniversalId;\n// export type SUniversalPColumnId = Branded<PObjectId, \"SUniversalPColumnId\", \"__pl_model_brand_2__\">;\n\nexport type ColumnUniversalKey =\n | LocalPObjectKey\n | GlobalPObjectKey\n | ColumnFilteredKey\n | ColumnDiscoveredKey\n | ColumnOverriddenKey;\n\nexport type ColumnUniversalId =\n | LocalPObjectId\n | GlobalPObjectId\n | ColumnFilteredId\n | ColumnDiscoveredId\n | ColumnOverriddenId;\n\n/**\n * Canonically serializes a column key to a branded string id. Accepts both\n * the new {@link ColumnUniversalKey} and the deprecated {@link UniversalPColumnId}\n * (anchored / old filtered object form).\n */\nexport function stringifyColumnId(id: ColumnUniversalKey | UniversalPColumnId): ColumnUniversalId {\n return canonicalizeJson(id) as ColumnUniversalId;\n}\n\n/**\n * Parses a canonically serialized column id back to its key form.\n */\nexport function parseColumnId(str: ColumnUniversalId): ColumnUniversalKey {\n return JSON.parse(str) as ColumnUniversalKey;\n}\n\nexport function parseColumnIdSafely(\n str: ColumnUniversalId,\n fallback = undefined,\n): ColumnUniversalKey | typeof fallback {\n try {\n return JSON.parse(str) as ColumnUniversalKey;\n } catch {\n return fallback;\n }\n}\n\n/**\n * Walk a rich column id down to its terminal leaf {@link PObjectId}.\n */\nexport function extractPObjectId(id: ColumnUniversalId | ColumnUniversalKey): PObjectId {\n if (isString(id)) {\n if (isPObjectId(id)) return id;\n\n const parsed =\n parseColumnIdSafely(id) ??\n throwError(`extractPObjectId: id \"${id}\" is not a valid canonical column id`);\n return extractPObjectId(parsed);\n }\n\n if (isPObjectKey(id)) return createPObjectId(id);\n if (isColumnFilteredKey(id)) return extractPObjectId(id.source);\n if (isColumnOverriddenKey(id)) return extractPObjectId(id.source);\n if (isColumnDiscoveredKey(id)) return extractPObjectId(id.column);\n\n throw new Error(`extractPObjectId: unrecognized column id structure: ${JSON.stringify(id)}`);\n}\n\n/**\n * Reconstruct the effective {@link PColumnSpec} for a rich column id by walking\n * the id chain from leaf to outermost wrapper, applying each layer's spec\n * transformation in the same order the corresponding recipe would.\n *\n * Layer semantics:\n * - Leaf ({@link LocalPObjectKey} / {@link GlobalPObjectKey}): no transformation.\n * - {@link ColumnDiscoveredKey}: pass-through, descends into `column`.\n * - {@link ColumnFilteredKey}: drops the axes whose positional index appears in\n * `axisFilters[i][0]` from the inner spec's `axesSpec` — mirrors\n * `ColumnFilteredRecipe.getSpec()`.\n * - {@link ColumnOverriddenKey}: applies `specOverrides` via\n * {@link applySpecOverrides} on top of the inner spec.\n */\nexport function reconstructSpecFromId(\n baseSpec: PColumnSpec,\n id: ColumnUniversalId | ColumnUniversalKey,\n): PColumnSpec {\n if (isString(id)) {\n if (isPObjectId(id)) return baseSpec;\n\n const parsed =\n parseColumnIdSafely(id) ??\n throwError(`reconstructSpecFromId: id \"${id}\" is not a valid canonical column id`);\n return reconstructSpecFromId(baseSpec, parsed);\n }\n\n if (isPObjectKey(id)) return baseSpec;\n if (isColumnDiscoveredKey(id)) return reconstructSpecFromId(baseSpec, id.column);\n if (isColumnFilteredKey(id)) {\n return applyAxisFilters(reconstructSpecFromId(baseSpec, id.source), id.axisFilters);\n }\n if (isColumnOverriddenKey(id)) {\n const inner = reconstructSpecFromId(baseSpec, id.source);\n return applySpecOverrides(inner, id.specOverrides);\n }\n\n throw new Error(`reconstructSpecFromId: unrecognized column id structure: ${JSON.stringify(id)}`);\n}\n"],"mappings":";;;;;;;;;;;;;;AA6EA,SAAgB,kBAAkB,IAAgE;CAChG,OAAO,iBAAiB,EAAE;AAC5B;;;;AAKA,SAAgB,cAAc,KAA4C;CACxE,OAAO,KAAK,MAAM,GAAG;AACvB;AAEA,SAAgB,oBACd,KACA,WAAW,KAAA,GAC2B;CACtC,IAAI;EACF,OAAO,KAAK,MAAM,GAAG;CACvB,QAAQ;EACN,OAAO;CACT;AACF;;;;AAKA,SAAgB,iBAAiB,IAAuD;CACtF,IAAI,SAAS,EAAE,GAAG;EAChB,IAAI,YAAY,EAAE,GAAG,OAAO;EAK5B,OAAO,iBAFL,oBAAoB,EAAE,KACtB,WAAW,yBAAyB,GAAG,qCAAqC,CAChD;CAChC;CAEA,IAAI,aAAa,EAAE,GAAG,OAAO,gBAAgB,EAAE;CAC/C,IAAI,oBAAoB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM;CAC9D,IAAI,sBAAsB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM;CAChE,IAAI,sBAAsB,EAAE,GAAG,OAAO,iBAAiB,GAAG,MAAM;CAEhE,MAAM,IAAI,MAAM,uDAAuD,KAAK,UAAU,EAAE,GAAG;AAC7F;;;;;;;;;;;;;;;AAgBA,SAAgB,sBACd,UACA,IACa;CACb,IAAI,SAAS,EAAE,GAAG;EAChB,IAAI,YAAY,EAAE,GAAG,OAAO;EAK5B,OAAO,sBAAsB,UAF3B,oBAAoB,EAAE,KACtB,WAAW,8BAA8B,GAAG,qCAAqC,CACtC;CAC/C;CAEA,IAAI,aAAa,EAAE,GAAG,OAAO;CAC7B,IAAI,sBAAsB,EAAE,GAAG,OAAO,sBAAsB,UAAU,GAAG,MAAM;CAC/E,IAAI,oBAAoB,EAAE,GACxB,OAAO,iBAAiB,sBAAsB,UAAU,GAAG,MAAM,GAAG,GAAG,WAAW;CAEpF,IAAI,sBAAsB,EAAE,GAE1B,OAAO,mBADO,sBAAsB,UAAU,GAAG,MACnB,GAAG,GAAG,aAAa;CAGnD,MAAM,IAAI,MAAM,4DAA4D,KAAK,UAAU,EAAE,GAAG;AAClG"}
1
+ {"version":3,"file":"ids.js","names":[],"sources":["../../../../src/drivers/pframe/spec/ids.ts"],"sourcesContent":["import type { AnchoredPColumnId } from \"./selectors\";\nimport {\n applyAxisFilters,\n isColumnFilteredKey,\n type ColumnFilteredId,\n type ColumnFilteredKey,\n type FilteredPColumnId,\n} from \"./filtered_column\";\nimport {\n createPObjectId,\n isGlobalPObjectKey,\n isLocalPObjectKey,\n isPObjectId,\n isPObjectKey,\n LocalPObjectKey,\n type GlobalPObjectId,\n type GlobalPObjectKey,\n type LocalPObjectId,\n type PObjectId,\n} from \"../../../pool\";\nimport {\n isColumnDiscoveredKey,\n type ColumnDiscoveredId,\n type ColumnDiscoveredKey,\n} from \"./discovered_column\";\nimport { throwError } from \"@milaboratories/helpers\";\nimport {\n applySpecOverrides,\n isColumnOverriddenKey,\n type ColumnOverriddenId,\n type ColumnOverriddenKey,\n} from \"./overridden\";\nimport { canonicalizeJson, parseJsonSafely } from \"../../../json\";\nimport { AxisSpec, PColumnSpec } from \"./spec\";\nimport { isString } from \"es-toolkit\";\n\n/**\n * Per-axis patches keyed by positional index in the base spec's `axesSpec`.\n *\n * Using position rather than `name` lets us disambiguate linker-style specs\n * that carry multiple axes with the same `name` differentiated by `domain` /\n * `contextDomain` (e.g. a `group`, `group/primary`, `group/secondary` triple).\n *\n * A patch at index `>= base.axesSpec.length` appends a new axis at that slot.\n */\nexport type AxisPatches = Record<number, Partial<AxisSpec>>;\n\n/**\n * Universal column identifier optionally anchored and optionally filtered.\n * @deprecated use {@link ColumnUniversalKey}\n */\nexport type UniversalPColumnId = AnchoredPColumnId | FilteredPColumnId;\n\n/**\n * Canonically serialized {@link UniversalPColumnId}.\n * @deprecated use {@link ColumnUniversalId}\n */\nexport type SUniversalPColumnId = ColumnUniversalId;\n// export type SUniversalPColumnId = Branded<PObjectId, \"SUniversalPColumnId\", \"__pl_model_brand_2__\">;\n\nexport type ColumnUniversalKey =\n | LocalPObjectKey\n | GlobalPObjectKey\n | ColumnFilteredKey\n | ColumnDiscoveredKey\n | ColumnOverriddenKey;\n\nexport type ColumnUniversalId =\n | LocalPObjectId\n | GlobalPObjectId\n | ColumnFilteredId\n | ColumnDiscoveredId\n | ColumnOverriddenId;\n\n/**\n * Canonically serializes a column key to a branded string id. Accepts both\n * the new {@link ColumnUniversalKey} and the deprecated {@link UniversalPColumnId}\n * (anchored / old filtered object form).\n */\nexport function stringifyColumnId(id: ColumnUniversalKey | UniversalPColumnId): ColumnUniversalId {\n return canonicalizeJson(id) as ColumnUniversalId;\n}\n\n/**\n * Parses a canonically serialized column id back to its key form.\n */\nexport function parseColumnId(str: ColumnUniversalId): ColumnUniversalKey {\n return JSON.parse(str) as ColumnUniversalKey;\n}\n\nexport function parseColumnIdSafely(\n str: ColumnUniversalId,\n fallback = undefined,\n): ColumnUniversalKey | typeof fallback {\n try {\n return JSON.parse(str) as ColumnUniversalKey;\n } catch {\n return fallback;\n }\n}\n\n/** Whether `value` is any of the five key forms a {@link ColumnUniversalId} serializes. */\nexport function isColumnUniversalKey(value: unknown): value is ColumnUniversalKey {\n return (\n isPObjectKey(value) ||\n isColumnFilteredKey(value) ||\n isColumnDiscoveredKey(value) ||\n isColumnOverriddenKey(value)\n );\n}\n\nexport function isColumnUniversalId(value: unknown): value is ColumnUniversalId {\n const key = isString(value) ? parseJsonSafely(value, false) : false;\n return key === false ? false : isColumnUniversalKey(key);\n}\n\n/**\n * A JSON string with its escape padding taken off, and how many passes that took.\n *\n * `layers` counts the `JSON.stringify` passes *above* the encoded value: a canonical id\n * is `layers: 0`, the same id run through `JSON.stringify` once more is `layers: 1`. Keep\n * it to put the value back the way it was found.\n */\nexport type PeeledJsonLayers = {\n readonly value: unknown;\n readonly layers: number;\n};\n\n/**\n * Take a value out of however many `JSON.stringify` passes wrapped it, or `undefined`\n * when `s` is not JSON at all.\n *\n * The one definition of \"how a value can be hiding inside a string\" — a block id can sit\n * under several layers of escaping, and a walk over object properties reaches none of\n * them. Callers differ in what they do at the bottom (this deliberately says nothing\n * about which values count as identifiers), but they must agree on the mechanics, or\n * \"what carries a block id\" ends up with two answers that drift.\n *\n * The gate is cheap and does NOT require any marker in the body: a filtered id whose\n * innermost leaf is a {@link LocalPObjectKey} carries no `__isRef`, so demanding one\n * would miss it.\n */\nexport function peelJsonLayers(s: string): PeeledJsonLayers | undefined {\n let current = s;\n let layers = 0;\n for (;;) {\n const c0 = current.charCodeAt(0);\n if (c0 !== 0x7b /* { */ && c0 !== 0x22 /* \" */) return undefined;\n let parsed: unknown;\n try {\n parsed = JSON.parse(current);\n } catch {\n return undefined;\n }\n // A pass that yielded another string was escape padding, so peel again. The string\n // is strictly shorter each time, which is what bounds the loop.\n if (isString(parsed)) {\n if (parsed.length >= current.length) return undefined;\n current = parsed;\n layers++;\n continue;\n }\n return { value: parsed, layers };\n }\n}\n\n/**\n * Rewrite every block id buried inside a column id.\n *\n * A {@link GlobalPObjectKey} leaf names its upstream by block id, and the wrapper key forms\n * nest by *string* id rather than by object — so a block id can sit under several layers of\n * JSON escaping, and `queriesQualifications` carries one in a map *key*. A caller that only\n * walks object properties never reaches any of them, which is why moving a column id between\n * projects needs this rather than a generic walk.\n *\n * Recursion re-canonicalizes bottom-up, so every level is canonical afterwards — including\n * the rebuilt `queriesQualifications`, whose keys the canonical form sorts. That is the\n * property a textual rewrite cannot have: redirecting an id that is a map key changes what\n * the sorted order should be, and only rebuilding restores it.\n *\n * Returns the input itself when no block id changed, so a caller mapping ids to themselves\n * gets its value back byte-for-byte and never re-serializes a stored id. Any `string` is\n * accepted for the same reason: a caller sweeping a params object cannot know which of its\n * strings are ids, and one that is not is returned as-is.\n *\n * @param remapBlockId old block id → new block id. Throw from it to reject an id that cannot\n * be mapped.\n */\nexport function remapColumnIdBlockIds<T extends string | ColumnUniversalKey>(\n id: T,\n remapBlockId: (blockId: string) => string,\n): T {\n const remapped = isString(id) ? remapIdString(id, remapBlockId) : remapKey(id, remapBlockId);\n return (remapped ?? id) as T;\n}\n\n/**\n * The string half of {@link remapColumnIdBlockIds}. `undefined` means \"nothing to change\",\n * which is what keeps an unaffected id from being re-serialized.\n *\n * Escape padding is peeled and put back, so an id that reached params through an extra\n * `JSON.stringify` is rewritten in place and comes back wrapped as it was found. A string\n * that does not peel to a column key is left alone: params hold ordinary strings too.\n */\nfunction remapIdString(id: string, remapBlockId: (blockId: string) => string): string | undefined {\n const peeled = peelJsonLayers(id);\n if (peeled === undefined || !isColumnUniversalKey(peeled.value)) return undefined;\n\n const remappedKey = remapKey(peeled.value, remapBlockId);\n if (remappedKey === undefined) return undefined;\n\n let rebuilt: string = stringifyColumnId(remappedKey);\n for (let layer = 0; layer < peeled.layers; layer++) rebuilt = JSON.stringify(rebuilt);\n return rebuilt;\n}\n\n/** The key half of {@link remapColumnIdBlockIds}. `undefined` means \"nothing to change\". */\nfunction remapKey(\n key: ColumnUniversalKey,\n remapBlockId: (blockId: string) => string,\n): ColumnUniversalKey | undefined {\n if (isGlobalPObjectKey(key)) {\n const blockId = remapBlockId(key.blockId);\n return blockId === key.blockId ? undefined : { ...key, blockId };\n }\n\n // A local leaf names its column by a path inside its own block — no block id.\n if (isLocalPObjectKey(key)) return undefined;\n\n if (isColumnFilteredKey(key)) {\n const source = remapIdString(key.source, remapBlockId);\n return source === undefined ? undefined : { ...key, source: source as ColumnUniversalId };\n }\n\n if (isColumnOverriddenKey(key)) {\n const source = remapIdString(key.source, remapBlockId);\n // Remapping preserves the id's shape, so `source` is still not an Overridden id.\n return source === undefined\n ? undefined\n : { ...key, source: source as ColumnOverriddenKey[\"source\"] };\n }\n\n if (isColumnDiscoveredKey(key)) return remapDiscoveredKey(key, remapBlockId);\n\n throw new Error(\n `remapColumnIdBlockIds: unrecognized column id structure: ${JSON.stringify(key)}`,\n );\n}\n\n/**\n * Discovered is the only key form carrying more than one nested id: the column it\n * discovered, one per linker hop, and one per entry in `queriesQualifications` — where the\n * id is the map key, not the value.\n */\nfunction remapDiscoveredKey(\n key: ColumnDiscoveredKey,\n remapBlockId: (blockId: string) => string,\n): ColumnDiscoveredKey | undefined {\n const column = remapIdString(key.column, remapBlockId);\n\n let pathChanged = false;\n const path = key.path?.map((item) => {\n const itemColumn = remapIdString(item.column, remapBlockId);\n if (itemColumn === undefined) return item;\n pathChanged = true;\n return { ...item, column: itemColumn as ColumnUniversalId };\n });\n\n let queriesChanged = false;\n const queriesQualifications =\n key.queriesQualifications &&\n (Object.fromEntries(\n Object.entries(key.queriesQualifications).map(([queryId, qualifications]) => {\n const remappedId = remapIdString(queryId, remapBlockId);\n if (remappedId === undefined) return [queryId, qualifications];\n queriesChanged = true;\n return [remappedId, qualifications];\n }),\n ) as ColumnDiscoveredKey[\"queriesQualifications\"]);\n\n if (column === undefined && !pathChanged && !queriesChanged) return undefined;\n return {\n ...key,\n ...(column !== undefined ? { column: column as ColumnUniversalId } : {}),\n ...(pathChanged ? { path } : {}),\n ...(queriesChanged ? { queriesQualifications } : {}),\n };\n}\n\n/**\n * Walk a rich column id down to its terminal leaf {@link PObjectId}.\n */\nexport function extractPObjectId(id: ColumnUniversalId | ColumnUniversalKey): PObjectId {\n if (isString(id)) {\n if (isPObjectId(id)) return id;\n\n const parsed =\n parseColumnIdSafely(id) ??\n throwError(`extractPObjectId: id \"${id}\" is not a valid canonical column id`);\n return extractPObjectId(parsed);\n }\n\n if (isPObjectKey(id)) return createPObjectId(id);\n if (isColumnFilteredKey(id)) return extractPObjectId(id.source);\n if (isColumnOverriddenKey(id)) return extractPObjectId(id.source);\n if (isColumnDiscoveredKey(id)) return extractPObjectId(id.column);\n\n throw new Error(`extractPObjectId: unrecognized column id structure: ${JSON.stringify(id)}`);\n}\n\n/**\n * Reconstruct the effective {@link PColumnSpec} for a rich column id by walking\n * the id chain from leaf to outermost wrapper, applying each layer's spec\n * transformation in the same order the corresponding recipe would.\n *\n * Layer semantics:\n * - Leaf ({@link LocalPObjectKey} / {@link GlobalPObjectKey}): no transformation.\n * - {@link ColumnDiscoveredKey}: pass-through, descends into `column`.\n * - {@link ColumnFilteredKey}: drops the axes whose positional index appears in\n * `axisFilters[i][0]` from the inner spec's `axesSpec` — mirrors\n * `ColumnFilteredRecipe.getSpec()`.\n * - {@link ColumnOverriddenKey}: applies `specOverrides` via\n * {@link applySpecOverrides} on top of the inner spec.\n */\nexport function reconstructSpecFromId(\n baseSpec: PColumnSpec,\n id: ColumnUniversalId | ColumnUniversalKey,\n): PColumnSpec {\n if (isString(id)) {\n if (isPObjectId(id)) return baseSpec;\n\n const parsed =\n parseColumnIdSafely(id) ??\n throwError(`reconstructSpecFromId: id \"${id}\" is not a valid canonical column id`);\n return reconstructSpecFromId(baseSpec, parsed);\n }\n\n if (isPObjectKey(id)) return baseSpec;\n if (isColumnDiscoveredKey(id)) return reconstructSpecFromId(baseSpec, id.column);\n if (isColumnFilteredKey(id)) {\n return applyAxisFilters(reconstructSpecFromId(baseSpec, id.source), id.axisFilters);\n }\n if (isColumnOverriddenKey(id)) {\n const inner = reconstructSpecFromId(baseSpec, id.source);\n return applySpecOverrides(inner, id.specOverrides);\n }\n\n throw new Error(`reconstructSpecFromId: unrecognized column id structure: ${JSON.stringify(id)}`);\n}\n"],"mappings":"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"}
@@ -46,6 +46,8 @@ exports.isColumnDiscoveredKey = require_discovered_column.isColumnDiscoveredKey;
46
46
  exports.isColumnFilteredId = require_filtered_column.isColumnFilteredId;
47
47
  exports.isColumnFilteredKey = require_filtered_column.isColumnFilteredKey;
48
48
  exports.isColumnOverriddenKey = require_overridden.isColumnOverriddenKey;
49
+ exports.isColumnUniversalId = require_ids.isColumnUniversalId;
50
+ exports.isColumnUniversalKey = require_ids.isColumnUniversalKey;
49
51
  exports.isEmptySpecDelta = require_overridden.isEmptySpecDelta;
50
52
  exports.isFilteredPColumn = require_filtered_column.isFilteredPColumn;
51
53
  exports.isLabelColumn = require_spec.isLabelColumn;
@@ -61,6 +63,7 @@ exports.parseColumnDiscoveredId = require_discovered_column.parseColumnDiscovere
61
63
  exports.parseColumnId = require_ids.parseColumnId;
62
64
  exports.parseColumnIdSafely = require_ids.parseColumnIdSafely;
63
65
  exports.parseColumnOverriddenId = require_overridden.parseColumnOverriddenId;
66
+ exports.peelJsonLayers = require_ids.peelJsonLayers;
64
67
  exports.readAnnotation = require_spec.readAnnotation;
65
68
  exports.readAnnotationJson = require_spec.readAnnotationJson;
66
69
  exports.readAnnotationJsonOrThrow = require_spec.readAnnotationJsonOrThrow;
@@ -71,6 +74,7 @@ exports.readMetadata = require_spec.readMetadata;
71
74
  exports.readMetadataJson = require_spec.readMetadataJson;
72
75
  exports.readMetadataJsonOrThrow = require_spec.readMetadataJsonOrThrow;
73
76
  exports.reconstructSpecFromId = require_ids.reconstructSpecFromId;
77
+ exports.remapColumnIdBlockIds = require_ids.remapColumnIdBlockIds;
74
78
  exports.resolveAnchors = require_anchored.resolveAnchors;
75
79
  exports.resolveAnnotationParents = require_spec.resolveAnnotationParents;
76
80
  exports.stringifyColumnDiscoveredId = require_discovered_column.stringifyColumnDiscoveredId;
@@ -1,9 +1,9 @@
1
1
  import { ColumnDiscoveredId, ColumnDiscoveredKey, createColumnDiscoveredId, createColumnDiscoveredKey, distillColumnDiscoveredKey, isColumnDiscoveredId, isColumnDiscoveredKey, parseColumnDiscoveredId, stringifyColumnDiscoveredId } from "./discovered_column.js";
2
2
  import { Annotation, AnnotationDataStatus, AnnotationJson, AxesId, AxesSpec, AxisId, AxisSpec, AxisSpecNormalized, AxisTree, AxisValueType, ColumnValueType, Domain, DomainJson, Metadata, MetadataJson, PAxisName, PColumn, PColumnIdAndSpec, PColumnName, PColumnSpec, PColumnSpecId, PDataColumnSpec, PUniversalColumnSpec, Trace, TraceEntry, ValueType, canonicalizeAxisId, canonicalizeAxisWithParents, getArrayFromAxisTree, getAxesId, getAxesTree, getAxisId, getColumnIdAndSpec, getDenormalizedAxesList, getNormalizedAxesList, getPColumnSpecId, getSetFromAxisTree, getTypeFromPColumnOrAxisSpec, isAxisId, isLabelColumn, isLinkerColumn, matchAxisId, readAnnotation, readAnnotationJson, readAnnotationJsonOrThrow, readDomain, readDomainJson, readDomainJsonOrThrow, readMetadata, readMetadataJson, readMetadataJsonOrThrow, resolveAnnotationParents } from "./spec.js";
3
3
  import { ColumnOverriddenId, ColumnOverriddenKey, SpecOverrides, applySpecOverrides, createColumnOverriddenId, createColumnOverriddenKey, deriveSpecDelta, distillColumnOverriddenKey, isColumnOverriddenKey, isEmptySpecDelta, mergeSpecOverrides, parseColumnOverriddenId, stringifyColumnOverriddenId, unwrapOverrides } from "./overridden.js";
4
- import { AxisPatches, ColumnUniversalId, ColumnUniversalKey, SUniversalPColumnId, UniversalPColumnId, extractPObjectId, parseColumnId, parseColumnIdSafely, reconstructSpecFromId, stringifyColumnId } from "./ids.js";
4
+ import { AxisPatches, ColumnUniversalId, ColumnUniversalKey, PeeledJsonLayers, SUniversalPColumnId, UniversalPColumnId, extractPObjectId, isColumnUniversalId, isColumnUniversalKey, parseColumnId, parseColumnIdSafely, peelJsonLayers, reconstructSpecFromId, remapColumnIdBlockIds, stringifyColumnId } from "./ids.js";
5
5
  import { AxisFilter, AxisFilterByIdx, AxisFilterByName, AxisFilterValue, ColumnFilteredId, ColumnFilteredKey, FilteredPColumn, FilteredPColumnId, applyAxisFilters, createColumnFilteredId, createColumnFilteredKey, isColumnFilteredId, isColumnFilteredKey, isFilteredPColumn, stringifyColumnFilteredId } from "./filtered_column.js";
6
6
  import { AnchoredIdDeriver, ResolveAnchorsOptions, resolveAnchors } from "./anchored.js";
7
7
  import { NativePObjectId, deriveNativeId } from "./native_id.js";
8
8
  import { AAxisSelector, ADomain, AnchorAxisIdOrRefBasic, AnchorAxisRef, AnchorAxisRefByIdx, AnchorAxisRefByMatcher, AnchorAxisRefByName, AnchorDomainRef, AnchoredColumnMatchStrategy, AnchoredPColumnId, AnchoredPColumnSelector, AxisQualification, LegacyAxisSelector, PColumnSelector, SingleAxisSelector, isAnchoredPColumnId, legacyColumnSelectorsToPredicate, matchAxis, matchMultiColumnSelector, matchPColumn, multiColumnSelectorsToPredicate } from "./selectors.js";
9
- export { AAxisSelector, ADomain, AnchorAxisIdOrRefBasic, AnchorAxisRef, AnchorAxisRefByIdx, AnchorAxisRefByMatcher, AnchorAxisRefByName, AnchorDomainRef, AnchoredColumnMatchStrategy, AnchoredIdDeriver, AnchoredPColumnId, AnchoredPColumnSelector, Annotation, AnnotationDataStatus, AnnotationJson, AxesId, AxesSpec, AxisFilter, AxisFilterByIdx, AxisFilterByName, AxisFilterValue, AxisId, AxisPatches, AxisQualification, AxisSpec, AxisSpecNormalized, AxisTree, AxisValueType, ColumnDiscoveredId, ColumnDiscoveredKey, ColumnFilteredId, ColumnFilteredKey, ColumnOverriddenId, ColumnOverriddenKey, ColumnUniversalId, ColumnUniversalKey, ColumnValueType, Domain, DomainJson, FilteredPColumn, FilteredPColumnId, LegacyAxisSelector, Metadata, MetadataJson, NativePObjectId, PAxisName, PColumn, PColumnIdAndSpec, PColumnName, PColumnSelector, PColumnSpec, PColumnSpecId, PDataColumnSpec, PUniversalColumnSpec, ResolveAnchorsOptions, SUniversalPColumnId, SingleAxisSelector, SpecOverrides, Trace, TraceEntry, UniversalPColumnId, ValueType, applyAxisFilters, applySpecOverrides, canonicalizeAxisId, canonicalizeAxisWithParents, createColumnDiscoveredId, createColumnDiscoveredKey, createColumnFilteredId, createColumnFilteredKey, createColumnOverriddenId, createColumnOverriddenKey, deriveNativeId, deriveSpecDelta, distillColumnDiscoveredKey, distillColumnOverriddenKey, extractPObjectId, getArrayFromAxisTree, getAxesId, getAxesTree, getAxisId, getColumnIdAndSpec, getDenormalizedAxesList, getNormalizedAxesList, getPColumnSpecId, getSetFromAxisTree, getTypeFromPColumnOrAxisSpec, isAnchoredPColumnId, isAxisId, isColumnDiscoveredId, isColumnDiscoveredKey, isColumnFilteredId, isColumnFilteredKey, isColumnOverriddenKey, isEmptySpecDelta, isFilteredPColumn, isLabelColumn, isLinkerColumn, legacyColumnSelectorsToPredicate, matchAxis, matchAxisId, matchMultiColumnSelector, matchPColumn, mergeSpecOverrides, multiColumnSelectorsToPredicate, parseColumnDiscoveredId, parseColumnId, parseColumnIdSafely, parseColumnOverriddenId, readAnnotation, readAnnotationJson, readAnnotationJsonOrThrow, readDomain, readDomainJson, readDomainJsonOrThrow, readMetadata, readMetadataJson, readMetadataJsonOrThrow, reconstructSpecFromId, resolveAnchors, resolveAnnotationParents, stringifyColumnDiscoveredId, stringifyColumnFilteredId, stringifyColumnId, stringifyColumnOverriddenId, unwrapOverrides };
9
+ export { AAxisSelector, ADomain, AnchorAxisIdOrRefBasic, AnchorAxisRef, AnchorAxisRefByIdx, AnchorAxisRefByMatcher, AnchorAxisRefByName, AnchorDomainRef, AnchoredColumnMatchStrategy, AnchoredIdDeriver, AnchoredPColumnId, AnchoredPColumnSelector, Annotation, AnnotationDataStatus, AnnotationJson, AxesId, AxesSpec, AxisFilter, AxisFilterByIdx, AxisFilterByName, AxisFilterValue, AxisId, AxisPatches, AxisQualification, AxisSpec, AxisSpecNormalized, AxisTree, AxisValueType, ColumnDiscoveredId, ColumnDiscoveredKey, ColumnFilteredId, ColumnFilteredKey, ColumnOverriddenId, ColumnOverriddenKey, ColumnUniversalId, ColumnUniversalKey, ColumnValueType, Domain, DomainJson, FilteredPColumn, FilteredPColumnId, LegacyAxisSelector, Metadata, MetadataJson, NativePObjectId, PAxisName, PColumn, PColumnIdAndSpec, PColumnName, PColumnSelector, PColumnSpec, PColumnSpecId, PDataColumnSpec, PUniversalColumnSpec, PeeledJsonLayers, ResolveAnchorsOptions, SUniversalPColumnId, SingleAxisSelector, SpecOverrides, Trace, TraceEntry, UniversalPColumnId, ValueType, applyAxisFilters, applySpecOverrides, canonicalizeAxisId, canonicalizeAxisWithParents, createColumnDiscoveredId, createColumnDiscoveredKey, createColumnFilteredId, createColumnFilteredKey, createColumnOverriddenId, createColumnOverriddenKey, deriveNativeId, deriveSpecDelta, distillColumnDiscoveredKey, distillColumnOverriddenKey, extractPObjectId, getArrayFromAxisTree, getAxesId, getAxesTree, getAxisId, getColumnIdAndSpec, getDenormalizedAxesList, getNormalizedAxesList, getPColumnSpecId, getSetFromAxisTree, getTypeFromPColumnOrAxisSpec, isAnchoredPColumnId, isAxisId, isColumnDiscoveredId, isColumnDiscoveredKey, isColumnFilteredId, isColumnFilteredKey, isColumnOverriddenKey, isColumnUniversalId, isColumnUniversalKey, isEmptySpecDelta, isFilteredPColumn, isLabelColumn, isLinkerColumn, legacyColumnSelectorsToPredicate, matchAxis, matchAxisId, matchMultiColumnSelector, matchPColumn, mergeSpecOverrides, multiColumnSelectorsToPredicate, parseColumnDiscoveredId, parseColumnId, parseColumnIdSafely, parseColumnOverriddenId, peelJsonLayers, readAnnotation, readAnnotationJson, readAnnotationJsonOrThrow, readDomain, readDomainJson, readDomainJsonOrThrow, readMetadata, readMetadataJson, readMetadataJsonOrThrow, reconstructSpecFromId, remapColumnIdBlockIds, resolveAnchors, resolveAnnotationParents, stringifyColumnDiscoveredId, stringifyColumnFilteredId, stringifyColumnId, stringifyColumnOverriddenId, unwrapOverrides };
@@ -2,8 +2,8 @@ import { Annotation, AnnotationJson, Domain, DomainJson, PAxisName, PColumnName,
2
2
  import { applyAxisFilters, createColumnFilteredId, createColumnFilteredKey, isColumnFilteredId, isColumnFilteredKey, isFilteredPColumn, stringifyColumnFilteredId } from "./filtered_column.js";
3
3
  import { createColumnDiscoveredId, createColumnDiscoveredKey, distillColumnDiscoveredKey, isColumnDiscoveredId, isColumnDiscoveredKey, parseColumnDiscoveredId, stringifyColumnDiscoveredId } from "./discovered_column.js";
4
4
  import { applySpecOverrides, createColumnOverriddenId, createColumnOverriddenKey, deriveSpecDelta, distillColumnOverriddenKey, isColumnOverriddenKey, isEmptySpecDelta, mergeSpecOverrides, parseColumnOverriddenId, stringifyColumnOverriddenId, unwrapOverrides } from "./overridden.js";
5
- import { extractPObjectId, parseColumnId, parseColumnIdSafely, reconstructSpecFromId, stringifyColumnId } from "./ids.js";
5
+ import { extractPObjectId, isColumnUniversalId, isColumnUniversalKey, parseColumnId, parseColumnIdSafely, peelJsonLayers, reconstructSpecFromId, remapColumnIdBlockIds, stringifyColumnId } from "./ids.js";
6
6
  import { AnchoredIdDeriver, resolveAnchors } from "./anchored.js";
7
7
  import { isAnchoredPColumnId, legacyColumnSelectorsToPredicate, matchAxis, matchMultiColumnSelector, matchPColumn, multiColumnSelectorsToPredicate } from "./selectors.js";
8
8
  import { deriveNativeId } from "./native_id.js";
9
- export { AnchoredIdDeriver, Annotation, AnnotationJson, Domain, DomainJson, PAxisName, PColumnName, ValueType, applyAxisFilters, applySpecOverrides, canonicalizeAxisId, canonicalizeAxisWithParents, createColumnDiscoveredId, createColumnDiscoveredKey, createColumnFilteredId, createColumnFilteredKey, createColumnOverriddenId, createColumnOverriddenKey, deriveNativeId, deriveSpecDelta, distillColumnDiscoveredKey, distillColumnOverriddenKey, extractPObjectId, getArrayFromAxisTree, getAxesId, getAxesTree, getAxisId, getColumnIdAndSpec, getDenormalizedAxesList, getNormalizedAxesList, getPColumnSpecId, getSetFromAxisTree, getTypeFromPColumnOrAxisSpec, isAnchoredPColumnId, isAxisId, isColumnDiscoveredId, isColumnDiscoveredKey, isColumnFilteredId, isColumnFilteredKey, isColumnOverriddenKey, isEmptySpecDelta, isFilteredPColumn, isLabelColumn, isLinkerColumn, legacyColumnSelectorsToPredicate, matchAxis, matchAxisId, matchMultiColumnSelector, matchPColumn, mergeSpecOverrides, multiColumnSelectorsToPredicate, parseColumnDiscoveredId, parseColumnId, parseColumnIdSafely, parseColumnOverriddenId, readAnnotation, readAnnotationJson, readAnnotationJsonOrThrow, readDomain, readDomainJson, readDomainJsonOrThrow, readMetadata, readMetadataJson, readMetadataJsonOrThrow, reconstructSpecFromId, resolveAnchors, resolveAnnotationParents, stringifyColumnDiscoveredId, stringifyColumnFilteredId, stringifyColumnId, stringifyColumnOverriddenId, unwrapOverrides };
9
+ export { AnchoredIdDeriver, Annotation, AnnotationJson, Domain, DomainJson, PAxisName, PColumnName, ValueType, applyAxisFilters, applySpecOverrides, canonicalizeAxisId, canonicalizeAxisWithParents, createColumnDiscoveredId, createColumnDiscoveredKey, createColumnFilteredId, createColumnFilteredKey, createColumnOverriddenId, createColumnOverriddenKey, deriveNativeId, deriveSpecDelta, distillColumnDiscoveredKey, distillColumnOverriddenKey, extractPObjectId, getArrayFromAxisTree, getAxesId, getAxesTree, getAxisId, getColumnIdAndSpec, getDenormalizedAxesList, getNormalizedAxesList, getPColumnSpecId, getSetFromAxisTree, getTypeFromPColumnOrAxisSpec, isAnchoredPColumnId, isAxisId, isColumnDiscoveredId, isColumnDiscoveredKey, isColumnFilteredId, isColumnFilteredKey, isColumnOverriddenKey, isColumnUniversalId, isColumnUniversalKey, isEmptySpecDelta, isFilteredPColumn, isLabelColumn, isLinkerColumn, legacyColumnSelectorsToPredicate, matchAxis, matchAxisId, matchMultiColumnSelector, matchPColumn, mergeSpecOverrides, multiColumnSelectorsToPredicate, parseColumnDiscoveredId, parseColumnId, parseColumnIdSafely, parseColumnOverriddenId, peelJsonLayers, readAnnotation, readAnnotationJson, readAnnotationJsonOrThrow, readDomain, readDomainJson, readDomainJsonOrThrow, readMetadata, readMetadataJson, readMetadataJsonOrThrow, reconstructSpecFromId, remapColumnIdBlockIds, resolveAnchors, resolveAnnotationParents, stringifyColumnDiscoveredId, stringifyColumnFilteredId, stringifyColumnId, stringifyColumnOverriddenId, unwrapOverrides };