@milaboratories/pl-model-common 1.36.1 → 1.37.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 (38) hide show
  1. package/dist/drivers/index.d.ts +12 -12
  2. package/dist/drivers/pframe/driver.d.ts +1 -1
  3. package/dist/drivers/pframe/index.d.ts +7 -7
  4. package/dist/drivers/pframe/query/query_spec.d.ts +1 -1
  5. package/dist/drivers/pframe/spec/anchored.d.ts +2 -2
  6. package/dist/drivers/pframe/spec/discovered_column.cjs.map +1 -1
  7. package/dist/drivers/pframe/spec/discovered_column.d.ts +1 -2
  8. package/dist/drivers/pframe/spec/discovered_column.d.ts.map +1 -1
  9. package/dist/drivers/pframe/spec/discovered_column.js.map +1 -1
  10. package/dist/drivers/pframe/spec/ids.d.ts +1 -1
  11. package/dist/drivers/pframe/spec/index.d.ts +4 -4
  12. package/dist/drivers/pframe/spec/selectors.cjs +47 -0
  13. package/dist/drivers/pframe/spec/selectors.cjs.map +1 -1
  14. package/dist/drivers/pframe/spec/selectors.d.ts +16 -1
  15. package/dist/drivers/pframe/spec/selectors.d.ts.map +1 -1
  16. package/dist/drivers/pframe/spec/selectors.js +46 -1
  17. package/dist/drivers/pframe/spec/selectors.js.map +1 -1
  18. package/dist/drivers/pframe/spec_driver.d.ts +3 -12
  19. package/dist/drivers/pframe/spec_driver.d.ts.map +1 -1
  20. package/dist/drivers/pframe/table_calculate.d.ts +1 -1
  21. package/dist/index.cjs +4 -0
  22. package/dist/index.d.ts +16 -16
  23. package/dist/index.js +3 -3
  24. package/dist/pool/index.d.ts +1 -1
  25. package/dist/pool/spec.d.ts +2 -1
  26. package/dist/pool/spec.d.ts.map +1 -1
  27. package/dist/ref.cjs +14 -0
  28. package/dist/ref.cjs.map +1 -1
  29. package/dist/ref.d.ts +35 -4
  30. package/dist/ref.d.ts.map +1 -1
  31. package/dist/ref.js +13 -1
  32. package/dist/ref.js.map +1 -1
  33. package/package.json +2 -2
  34. package/src/drivers/pframe/spec/discovered_column.ts +1 -2
  35. package/src/drivers/pframe/spec/selectors.ts +85 -0
  36. package/src/drivers/pframe/spec_driver.ts +1 -10
  37. package/src/ref.test.ts +73 -1
  38. package/src/ref.ts +59 -3
package/src/ref.test.ts CHANGED
@@ -1,7 +1,10 @@
1
1
  import { describe, expect, it } from "vitest";
2
- import { createPlRef, isPlRef, isPrimaryRef } from "./ref";
2
+ import type { PObjectId } from "./pool/spec";
3
+ import { createEnrichmentRef, createPlRef, isEnrichmentRef, isPlRef, isPrimaryRef } from "./ref";
3
4
 
4
5
  const sampleRef = createPlRef("block1", "output1", true);
6
+ const sampleHit = "hit-1" as PObjectId;
7
+ const sampleLinker = "linker-1" as PObjectId;
5
8
 
6
9
  describe("isPrimaryRef", () => {
7
10
  it("returns true for a valid PrimaryRef", () => {
@@ -31,7 +34,76 @@ describe("isPlRef", () => {
31
34
  expect(isPlRef({ __isPrimaryRef: "v1", column: sampleRef })).toBe(false);
32
35
  });
33
36
 
37
+ it("returns false for an EnrichmentRef", () => {
38
+ expect(isPlRef({ __isEnrichment: "v1", hit: sampleHit, path: [] })).toBe(false);
39
+ });
40
+
34
41
  it("returns true for a PlRef", () => {
35
42
  expect(isPlRef(sampleRef)).toBe(true);
36
43
  });
37
44
  });
45
+
46
+ describe("isEnrichmentRef", () => {
47
+ it("returns true for an EnrichmentRef with empty path", () => {
48
+ expect(isEnrichmentRef({ __isEnrichment: "v1", hit: sampleHit, path: [] })).toBe(true);
49
+ });
50
+
51
+ it("returns true for an EnrichmentRef with linker steps", () => {
52
+ expect(
53
+ isEnrichmentRef({
54
+ __isEnrichment: "v1",
55
+ hit: sampleHit,
56
+ path: [{ type: "linker", linker: sampleLinker }],
57
+ }),
58
+ ).toBe(true);
59
+ });
60
+
61
+ it("returns false for a PrimaryRef", () => {
62
+ expect(isEnrichmentRef({ __isPrimaryRef: "v1", column: sampleRef })).toBe(false);
63
+ });
64
+
65
+ it("returns false for a PlRef", () => {
66
+ expect(isEnrichmentRef(sampleRef)).toBe(false);
67
+ });
68
+
69
+ it("returns false for null", () => {
70
+ expect(isEnrichmentRef(null)).toBe(false);
71
+ });
72
+ });
73
+
74
+ describe("createEnrichmentRef", () => {
75
+ const sampleQual = { axis: { name: "a" }, contextDomain: { d: "1" } };
76
+
77
+ it("creates an EnrichmentRef with a non-empty linker path", () => {
78
+ const ref = createEnrichmentRef(sampleHit, {
79
+ path: [{ type: "linker", linker: sampleLinker }],
80
+ });
81
+ expect(ref).toEqual({
82
+ __isEnrichment: "v1",
83
+ hit: sampleHit,
84
+ path: [{ type: "linker", linker: sampleLinker }],
85
+ });
86
+ expect("qualifications" in ref).toBe(false);
87
+ });
88
+
89
+ it("omits path when none given", () => {
90
+ const ref = createEnrichmentRef(sampleHit);
91
+ expect(ref).toEqual({ __isEnrichment: "v1", hit: sampleHit });
92
+ expect("path" in ref).toBe(false);
93
+ });
94
+
95
+ it("omits empty path", () => {
96
+ const ref = createEnrichmentRef(sampleHit, { path: [] });
97
+ expect("path" in ref).toBe(false);
98
+ });
99
+
100
+ it("attaches non-empty qualifications", () => {
101
+ const ref = createEnrichmentRef(sampleHit, { qualifications: [sampleQual] });
102
+ expect(ref.qualifications).toEqual([sampleQual]);
103
+ });
104
+
105
+ it("omits empty qualifications array", () => {
106
+ const ref = createEnrichmentRef(sampleHit, { qualifications: [] });
107
+ expect("qualifications" in ref).toBe(false);
108
+ });
109
+ });
package/src/ref.ts CHANGED
@@ -1,4 +1,6 @@
1
1
  import { z } from "zod";
2
+ import type { AxisQualification } from "./drivers/pframe/spec/selectors";
3
+ import type { PObjectId } from "./pool/spec";
2
4
 
3
5
  export const PlRef = z
4
6
  .object({
@@ -125,11 +127,65 @@ export function createPrimaryRef(column: PlRef, filter?: PlRef): PrimaryRef {
125
127
  /** Block args accept either form — backward compatible. */
126
128
  export type DatasetInput = PlRef | PrimaryRef;
127
129
 
128
- /** Dataset option with optional filter choices. */
129
- export type DatasetOption = Option & {
130
- readonly filters?: readonly Option[];
130
+ /** Many-to-one linker hop. */
131
+ export type EnrichmentLinkerStep = {
132
+ readonly type: "linker";
133
+ readonly linker: PObjectId;
131
134
  };
132
135
 
136
+ /** Step from primary to hit. `path[0]` applied first. */
137
+ export type EnrichmentStep = EnrichmentLinkerStep;
138
+
139
+ /**
140
+ * Enrichment column reached via {@link path} linker hops; omitted means zero-hop.
141
+ * `hit` and `path[].linker` are global-form {@link PObjectId}s
142
+ * (`canonicalize({ __isRef: true, blockId, name })`) which the workflow decodes
143
+ * to a PlRef before resolving. For a prerun-sourced hop, supply a resolved
144
+ * `{spec, data}` map in place of the id — `tableBuilder` accepts both.
145
+ */
146
+ export type EnrichmentRef = {
147
+ readonly __isEnrichment: "v1";
148
+ readonly hit: PObjectId;
149
+ readonly path?: readonly EnrichmentStep[];
150
+ readonly qualifications?: readonly AxisQualification[];
151
+ };
152
+
153
+ export function isEnrichmentRef(value: unknown): value is EnrichmentRef {
154
+ return (
155
+ typeof value === "object" &&
156
+ value !== null &&
157
+ (value as { __isEnrichment?: unknown }).__isEnrichment === "v1" &&
158
+ "hit" in value
159
+ );
160
+ }
161
+
162
+ export type CreateEnrichmentRefOptions = {
163
+ readonly path?: readonly EnrichmentStep[];
164
+ readonly qualifications?: readonly AxisQualification[];
165
+ };
166
+
167
+ export function createEnrichmentRef(
168
+ hit: PObjectId,
169
+ options: CreateEnrichmentRefOptions = {},
170
+ ): EnrichmentRef {
171
+ const { path, qualifications } = options;
172
+ return {
173
+ __isEnrichment: "v1",
174
+ hit,
175
+ ...(path !== undefined && path.length > 0 ? { path } : {}),
176
+ ...(qualifications !== undefined && qualifications.length > 0 ? { qualifications } : {}),
177
+ };
178
+ }
179
+
180
+ /** {@link EnrichmentRef} plus the export header label. */
181
+ export type LabeledEnrichmentRef = {
182
+ readonly ref: EnrichmentRef;
183
+ readonly label: string;
184
+ };
185
+
186
+ /** Auto-attached enrichment payload; not user-picked. */
187
+ export type LabeledEnrichmentRefs = readonly LabeledEnrichmentRef[];
188
+
133
189
  /** Compare two PlRefs and returns true if they are qual */
134
190
  export function plRefsEqual(ref1: PlRef, ref2: PlRef, ignoreEnrichments: boolean = false) {
135
191
  return (