@platforma-sdk/model 1.54.10 → 1.54.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/components/PlDataTable/state-migration.cjs.map +1 -1
- package/dist/components/PlDataTable/state-migration.js.map +1 -1
- package/dist/components/PlDataTable/table.cjs +11 -2
- package/dist/components/PlDataTable/table.cjs.map +1 -1
- package/dist/components/PlDataTable/table.d.ts.map +1 -1
- package/dist/components/PlDataTable/table.js +12 -3
- package/dist/components/PlDataTable/table.js.map +1 -1
- package/dist/components/PlDataTable/v5.d.ts +7 -4
- package/dist/components/PlDataTable/v5.d.ts.map +1 -1
- package/dist/filters/converters/filterToQuery.cjs +3 -4
- package/dist/filters/converters/filterToQuery.cjs.map +1 -1
- package/dist/filters/converters/filterToQuery.d.ts +1 -1
- package/dist/filters/converters/filterToQuery.d.ts.map +1 -1
- package/dist/filters/converters/filterToQuery.js +3 -4
- package/dist/filters/converters/filterToQuery.js.map +1 -1
- package/dist/filters/distill.cjs.map +1 -1
- package/dist/filters/distill.d.ts +3 -2
- package/dist/filters/distill.d.ts.map +1 -1
- package/dist/filters/distill.js.map +1 -1
- package/dist/filters/traverse.cjs +7 -3
- package/dist/filters/traverse.cjs.map +1 -1
- package/dist/filters/traverse.d.ts +14 -12
- package/dist/filters/traverse.d.ts.map +1 -1
- package/dist/filters/traverse.js +7 -3
- package/dist/filters/traverse.js.map +1 -1
- package/dist/package.json.cjs +1 -1
- package/dist/package.json.js +1 -1
- package/package.json +6 -6
- package/src/components/PlDataTable/state-migration.ts +4 -4
- package/src/components/PlDataTable/table.ts +16 -3
- package/src/components/PlDataTable/v5.ts +9 -5
- package/src/filters/converters/filterToQuery.ts +8 -7
- package/src/filters/distill.ts +19 -11
- package/src/filters/traverse.ts +44 -24
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"filterToQuery.js","sources":["../../../src/filters/converters/filterToQuery.ts"],"sourcesContent":["import { assertNever } from \"@milaboratories/pl-model-common\";\nimport type {\n FilterSpec,\n FilterSpecLeaf,\n PTableColumnId,\n SingleAxisSelector,\n SpecQueryExpression,\n} from \"@milaboratories/pl-model-common\";\nimport { traverseFilterSpec } from \"../traverse\";\n\n/** Parses a CanonicalizedJson<PTableColumnId> string into a SpecQueryExpression reference. */\nfunction resolveColumnRef(columnStr: string): SpecQueryExpression {\n const parsed = JSON.parse(columnStr) as PTableColumnId;\n if (parsed.type === \"axis\") {\n return { type: \"axisRef\", value: parsed.id as SingleAxisSelector };\n }\n return { type: \"columnRef\", value: parsed.id };\n}\n\n/** Converts a FilterSpec tree into a SpecQueryExpression. */\nexport function filterSpecToSpecQueryExpr(\n filter: FilterSpec<FilterSpecLeaf<string>>,\n): SpecQueryExpression {\n return traverseFilterSpec(filter, {\n leaf: leafToSpecQueryExpr,\n and: (inputs) => {\n if (inputs.length === 0) {\n throw new Error(\"AND filter requires at least one operand\");\n }\n return { type: \"and\", input: inputs };\n },\n or: (inputs) => {\n if (inputs.length === 0) {\n throw new Error(\"OR filter requires at least one operand\");\n }\n return { type: \"or\", input: inputs };\n },\n not: (input) => ({ type: \"not\", input }),\n });\n}\n\nfunction leafToSpecQueryExpr(filter: FilterSpecLeaf<string>): SpecQueryExpression {\n switch (filter.type) {\n case \"patternEquals\":\n return {\n type: \"stringEquals\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n caseInsensitive: false,\n };\n case \"patternNotEquals\":\n return {\n type: \"not\",\n input: {\n type: \"stringEquals\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n caseInsensitive: false,\n },\n };\n case \"patternContainSubsequence\":\n return {\n type: \"stringContains\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n caseInsensitive: false,\n };\n case \"patternNotContainSubsequence\":\n return {\n type: \"not\",\n input: {\n type: \"stringContains\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n caseInsensitive: false,\n },\n };\n case \"patternMatchesRegularExpression\":\n return {\n type: \"stringRegex\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n };\n case \"patternFuzzyContainSubsequence\":\n return {\n type: \"stringContainsFuzzy\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n maxEdits: filter.maxEdits ?? 1,\n caseInsensitive: false,\n substitutionsOnly: filter.substitutionsOnly ?? false,\n wildcard: filter.wildcard ?? null,\n };\n\n case \"equal\":\n return {\n type: \"numericComparison\",\n operand: \"eq\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"notEqual\":\n return {\n type: \"numericComparison\",\n operand: \"ne\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"lessThan\":\n return {\n type: \"numericComparison\",\n operand: \"lt\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"greaterThan\":\n return {\n type: \"numericComparison\",\n operand: \"gt\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"lessThanOrEqual\":\n return {\n type: \"numericComparison\",\n operand: \"le\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"greaterThanOrEqual\":\n return {\n type: \"numericComparison\",\n operand: \"ge\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n\n case \"equalToColumn\":\n return {\n type: \"numericComparison\",\n operand: \"eq\",\n left: resolveColumnRef(filter.column),\n right: resolveColumnRef(filter.rhs),\n };\n case \"lessThanColumn\": {\n const left = resolveColumnRef(filter.column);\n const right = resolveColumnRef(filter.rhs);\n if (filter.minDiff !== undefined && filter.minDiff !== 0) {\n return {\n type: \"numericComparison\",\n operand: \"lt\",\n left: {\n type: \"numericBinary\",\n operand: \"add\",\n left,\n right: { type: \"constant\", value: filter.minDiff },\n },\n right,\n };\n }\n return { type: \"numericComparison\", operand: \"lt\", left, right };\n }\n case \"greaterThanColumn\": {\n const left = resolveColumnRef(filter.column);\n const right = resolveColumnRef(filter.rhs);\n if (filter.minDiff !== undefined && filter.minDiff !== 0) {\n return {\n type: \"numericComparison\",\n operand: \"gt\",\n left: {\n type: \"numericBinary\",\n operand: \"add\",\n left,\n right: { type: \"constant\", value: filter.minDiff },\n },\n right,\n };\n }\n return { type: \"numericComparison\", operand: \"gt\", left, right };\n }\n case \"lessThanColumnOrEqual\": {\n const left = resolveColumnRef(filter.column);\n const right = resolveColumnRef(filter.rhs);\n if (filter.minDiff !== undefined && filter.minDiff !== 0) {\n return {\n type: \"numericComparison\",\n operand: \"le\",\n left: {\n type: \"numericBinary\",\n operand: \"add\",\n left,\n right: { type: \"constant\", value: filter.minDiff },\n },\n right,\n };\n }\n return { type: \"numericComparison\", operand: \"le\", left, right };\n }\n case \"greaterThanColumnOrEqual\": {\n const left = resolveColumnRef(filter.column);\n const right = resolveColumnRef(filter.rhs);\n if (filter.minDiff !== undefined && filter.minDiff !== 0) {\n return {\n type: \"numericComparison\",\n operand: \"ge\",\n left: {\n type: \"numericBinary\",\n operand: \"add\",\n left,\n right: { type: \"constant\", value: filter.minDiff },\n },\n right,\n };\n }\n return { type: \"numericComparison\", operand: \"ge\", left, right };\n }\n\n case \"inSet\":\n return {\n type: \"isIn\",\n input: resolveColumnRef(filter.column),\n set: filter.value,\n };\n case \"notInSet\":\n return {\n type: \"not\",\n input: {\n type: \"isIn\",\n input: resolveColumnRef(filter.column),\n set: filter.value,\n },\n };\n\n case \"isNA\":\n return {\n type: \"isNull\",\n input: resolveColumnRef(filter.column),\n };\n case \"isNotNA\":\n return {\n type: \"not\",\n input: {\n type: \"isNull\",\n input: resolveColumnRef(filter.column),\n },\n };\n\n case \"ifNa\":\n return {\n type: \"ifNull\",\n input: resolveColumnRef(filter.column),\n replacement: { type: \"constant\", value: filter.replacement },\n };\n\n case \"topN\":\n case \"bottomN\":\n throw new Error(`Filter type \"${filter.type}\" is not supported in query expressions`);\n\n case undefined:\n throw new Error(\"Filter type is undefined\");\n\n default:\n assertNever(filter);\n }\n}\n"],"names":[],"mappings":";;;AAUA;AACA,SAAS,gBAAgB,CAAC,SAAiB,EAAA;IACzC,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,SAAS,CAAmB;AACtD,IAAA,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM,EAAE;QAC1B,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,CAAC,EAAwB,EAAE;IACpE;IACA,OAAO,EAAE,IAAI,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,CAAC,EAAE,EAAE;AAChD;AAEA;AACM,SAAU,yBAAyB,CACvC,MAA0C,EAAA;IAE1C,OAAO,kBAAkB,CAAC,MAAM,EAAE;AAChC,QAAA,IAAI,EAAE,mBAAmB;AACzB,QAAA,GAAG,EAAE,CAAC,MAAM,KAAI;AACd,YAAA,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;AACvB,gBAAA,MAAM,IAAI,KAAK,CAAC,0CAA0C,CAAC;YAC7D;YACA,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,EAAE;QACvC,CAAC;AACD,QAAA,EAAE,EAAE,CAAC,MAAM,KAAI;AACb,YAAA,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE;AACvB,gBAAA,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC;YAC5D;YACA,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE;QACtC,CAAC;AACD,QAAA,GAAG,EAAE,CAAC,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AACzC,KAAA,CAAC;AACJ;AAEA,SAAS,mBAAmB,CAAC,MAA8B,EAAA;AACzD,IAAA,QAAQ,MAAM,CAAC,IAAI;AACjB,QAAA,KAAK,eAAe;YAClB,OAAO;AACL,gBAAA,IAAI,EAAE,cAAc;AACpB,gBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACtC,KAAK,EAAE,MAAM,CAAC,KAAK;AACnB,gBAAA,eAAe,EAAE,KAAK;aACvB;AACH,QAAA,KAAK,kBAAkB;YACrB,OAAO;AACL,gBAAA,IAAI,EAAE,KAAK;AACX,gBAAA,KAAK,EAAE;AACL,oBAAA,IAAI,EAAE,cAAc;AACpB,oBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;oBACtC,KAAK,EAAE,MAAM,CAAC,KAAK;AACnB,oBAAA,eAAe,EAAE,KAAK;AACvB,iBAAA;aACF;AACH,QAAA,KAAK,2BAA2B;YAC9B,OAAO;AACL,gBAAA,IAAI,EAAE,gBAAgB;AACtB,gBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACtC,KAAK,EAAE,MAAM,CAAC,KAAK;AACnB,gBAAA,eAAe,EAAE,KAAK;aACvB;AACH,QAAA,KAAK,8BAA8B;YACjC,OAAO;AACL,gBAAA,IAAI,EAAE,KAAK;AACX,gBAAA,KAAK,EAAE;AACL,oBAAA,IAAI,EAAE,gBAAgB;AACtB,oBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;oBACtC,KAAK,EAAE,MAAM,CAAC,KAAK;AACnB,oBAAA,eAAe,EAAE,KAAK;AACvB,iBAAA;aACF;AACH,QAAA,KAAK,iCAAiC;YACpC,OAAO;AACL,gBAAA,IAAI,EAAE,aAAa;AACnB,gBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACtC,KAAK,EAAE,MAAM,CAAC,KAAK;aACpB;AACH,QAAA,KAAK,gCAAgC;YACnC,OAAO;AACL,gBAAA,IAAI,EAAE,qBAAqB;AAC3B,gBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACtC,KAAK,EAAE,MAAM,CAAC,KAAK;AACnB,gBAAA,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,CAAC;AAC9B,gBAAA,eAAe,EAAE,KAAK;AACtB,gBAAA,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,IAAI,KAAK;AACpD,gBAAA,QAAQ,EAAE,MAAM,CAAC,QAAQ,IAAI,IAAI;aAClC;AAEH,QAAA,KAAK,OAAO;YACV,OAAO;AACL,gBAAA,IAAI,EAAE,mBAAmB;AACzB,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACrC,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE;aAC7C;AACH,QAAA,KAAK,UAAU;YACb,OAAO;AACL,gBAAA,IAAI,EAAE,mBAAmB;AACzB,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACrC,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE;aAC7C;AACH,QAAA,KAAK,UAAU;YACb,OAAO;AACL,gBAAA,IAAI,EAAE,mBAAmB;AACzB,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACrC,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE;aAC7C;AACH,QAAA,KAAK,aAAa;YAChB,OAAO;AACL,gBAAA,IAAI,EAAE,mBAAmB;AACzB,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACrC,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE;aAC7C;AACH,QAAA,KAAK,iBAAiB;YACpB,OAAO;AACL,gBAAA,IAAI,EAAE,mBAAmB;AACzB,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACrC,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE;aAC7C;AACH,QAAA,KAAK,oBAAoB;YACvB,OAAO;AACL,gBAAA,IAAI,EAAE,mBAAmB;AACzB,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACrC,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE;aAC7C;AAEH,QAAA,KAAK,eAAe;YAClB,OAAO;AACL,gBAAA,IAAI,EAAE,mBAAmB;AACzB,gBAAA,OAAO,EAAE,IAAI;AACb,gBAAA,IAAI,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;AACrC,gBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC;aACpC;QACH,KAAK,gBAAgB,EAAE;YACrB,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;YAC5C,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC;AAC1C,YAAA,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE;gBACxD,OAAO;AACL,oBAAA,IAAI,EAAE,mBAAmB;AACzB,oBAAA,OAAO,EAAE,IAAI;AACb,oBAAA,IAAI,EAAE;AACJ,wBAAA,IAAI,EAAE,eAAe;AACrB,wBAAA,OAAO,EAAE,KAAK;wBACd,IAAI;wBACJ,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE;AACnD,qBAAA;oBACD,KAAK;iBACN;YACH;AACA,YAAA,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE;QAClE;QACA,KAAK,mBAAmB,EAAE;YACxB,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;YAC5C,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC;AAC1C,YAAA,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE;gBACxD,OAAO;AACL,oBAAA,IAAI,EAAE,mBAAmB;AACzB,oBAAA,OAAO,EAAE,IAAI;AACb,oBAAA,IAAI,EAAE;AACJ,wBAAA,IAAI,EAAE,eAAe;AACrB,wBAAA,OAAO,EAAE,KAAK;wBACd,IAAI;wBACJ,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE;AACnD,qBAAA;oBACD,KAAK;iBACN;YACH;AACA,YAAA,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE;QAClE;QACA,KAAK,uBAAuB,EAAE;YAC5B,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;YAC5C,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC;AAC1C,YAAA,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE;gBACxD,OAAO;AACL,oBAAA,IAAI,EAAE,mBAAmB;AACzB,oBAAA,OAAO,EAAE,IAAI;AACb,oBAAA,IAAI,EAAE;AACJ,wBAAA,IAAI,EAAE,eAAe;AACrB,wBAAA,OAAO,EAAE,KAAK;wBACd,IAAI;wBACJ,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE;AACnD,qBAAA;oBACD,KAAK;iBACN;YACH;AACA,YAAA,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE;QAClE;QACA,KAAK,0BAA0B,EAAE;YAC/B,MAAM,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;YAC5C,MAAM,KAAK,GAAG,gBAAgB,CAAC,MAAM,CAAC,GAAG,CAAC;AAC1C,YAAA,IAAI,MAAM,CAAC,OAAO,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,KAAK,CAAC,EAAE;gBACxD,OAAO;AACL,oBAAA,IAAI,EAAE,mBAAmB;AACzB,oBAAA,OAAO,EAAE,IAAI;AACb,oBAAA,IAAI,EAAE;AACJ,wBAAA,IAAI,EAAE,eAAe;AACrB,wBAAA,OAAO,EAAE,KAAK;wBACd,IAAI;wBACJ,KAAK,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,OAAO,EAAE;AACnD,qBAAA;oBACD,KAAK;iBACN;YACH;AACA,YAAA,OAAO,EAAE,IAAI,EAAE,mBAAmB,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE;QAClE;AAEA,QAAA,KAAK,OAAO;YACV,OAAO;AACL,gBAAA,IAAI,EAAE,MAAM;AACZ,gBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACtC,GAAG,EAAE,MAAM,CAAC,KAAK;aAClB;AACH,QAAA,KAAK,UAAU;YACb,OAAO;AACL,gBAAA,IAAI,EAAE,KAAK;AACX,gBAAA,KAAK,EAAE;AACL,oBAAA,IAAI,EAAE,MAAM;AACZ,oBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;oBACtC,GAAG,EAAE,MAAM,CAAC,KAAK;AAClB,iBAAA;aACF;AAEH,QAAA,KAAK,MAAM;YACT,OAAO;AACL,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;aACvC;AACH,QAAA,KAAK,SAAS;YACZ,OAAO;AACL,gBAAA,IAAI,EAAE,KAAK;AACX,gBAAA,KAAK,EAAE;AACL,oBAAA,IAAI,EAAE,QAAQ;AACd,oBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;AACvC,iBAAA;aACF;AAEH,QAAA,KAAK,MAAM;YACT,OAAO;AACL,gBAAA,IAAI,EAAE,QAAQ;AACd,gBAAA,KAAK,EAAE,gBAAgB,CAAC,MAAM,CAAC,MAAM,CAAC;gBACtC,WAAW,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,KAAK,EAAE,MAAM,CAAC,WAAW,EAAE;aAC7D;AAEH,QAAA,KAAK,MAAM;AACX,QAAA,KAAK,SAAS;YACZ,MAAM,IAAI,KAAK,CAAC,CAAA,aAAA,EAAgB,MAAM,CAAC,IAAI,CAAA,uCAAA,CAAyC,CAAC;AAEvF,QAAA,KAAK,SAAS;AACZ,YAAA,MAAM,IAAI,KAAK,CAAC,0BAA0B,CAAC;AAE7C,QAAA;YACE,WAAW,CAAC,MAAM,CAAC;;AAEzB;;;;"}
|
|
1
|
+
{"version":3,"file":"filterToQuery.js","sources":["../../../src/filters/converters/filterToQuery.ts"],"sourcesContent":["import { assertNever } from \"@milaboratories/pl-model-common\";\nimport type {\n FilterSpec,\n FilterSpecLeaf,\n PTableColumnId,\n SingleAxisSelector,\n SpecQueryExpression,\n} from \"@milaboratories/pl-model-common\";\nimport { traverseFilterSpec } from \"../traverse\";\n\n/** Parses a CanonicalizedJson<PTableColumnId> string into a SpecQueryExpression reference. */\nfunction resolveColumnRef(columnStr: string): SpecQueryExpression {\n const parsed = JSON.parse(columnStr) as PTableColumnId;\n return parsed.type === \"axis\"\n ? { type: \"axisRef\", value: parsed.id as SingleAxisSelector }\n : { type: \"columnRef\", value: parsed.id };\n}\n\n/** Converts a FilterSpec tree into a SpecQueryExpression. */\nexport function filterSpecToSpecQueryExpr<Leaf extends FilterSpecLeaf<string>>(\n filter: FilterSpec<Leaf>,\n): SpecQueryExpression {\n return traverseFilterSpec(filter, {\n leaf: leafToSpecQueryExpr,\n and: (inputs) => {\n if (inputs.length === 0) {\n throw new Error(\"AND filter requires at least one operand\");\n }\n return { type: \"and\", input: inputs };\n },\n or: (inputs) => {\n if (inputs.length === 0) {\n throw new Error(\"OR filter requires at least one operand\");\n }\n return { type: \"or\", input: inputs };\n },\n not: (input) => ({ type: \"not\", input }),\n });\n}\n\nfunction leafToSpecQueryExpr<Leaf extends FilterSpecLeaf<string>>(\n filter: Leaf,\n): SpecQueryExpression {\n switch (filter.type) {\n case \"patternEquals\":\n return {\n type: \"stringEquals\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n caseInsensitive: false,\n };\n case \"patternNotEquals\":\n return {\n type: \"not\",\n input: {\n type: \"stringEquals\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n caseInsensitive: false,\n },\n };\n case \"patternContainSubsequence\":\n return {\n type: \"stringContains\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n caseInsensitive: false,\n };\n case \"patternNotContainSubsequence\":\n return {\n type: \"not\",\n input: {\n type: \"stringContains\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n caseInsensitive: false,\n },\n };\n case \"patternMatchesRegularExpression\":\n return {\n type: \"stringRegex\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n };\n case \"patternFuzzyContainSubsequence\":\n return {\n type: \"stringContainsFuzzy\",\n input: resolveColumnRef(filter.column),\n value: filter.value,\n maxEdits: filter.maxEdits ?? 1,\n caseInsensitive: false,\n substitutionsOnly: filter.substitutionsOnly ?? false,\n wildcard: filter.wildcard ?? null,\n };\n\n case \"equal\":\n return {\n type: \"numericComparison\",\n operand: \"eq\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"notEqual\":\n return {\n type: \"numericComparison\",\n operand: \"ne\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"lessThan\":\n return {\n type: \"numericComparison\",\n operand: \"lt\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"greaterThan\":\n return {\n type: \"numericComparison\",\n operand: \"gt\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"lessThanOrEqual\":\n return {\n type: \"numericComparison\",\n operand: \"le\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n case \"greaterThanOrEqual\":\n return {\n type: \"numericComparison\",\n operand: \"ge\",\n left: resolveColumnRef(filter.column),\n right: { type: \"constant\", value: filter.x },\n };\n\n case \"equalToColumn\":\n return {\n type: \"numericComparison\",\n operand: \"eq\",\n left: resolveColumnRef(filter.column),\n right: resolveColumnRef(filter.rhs),\n };\n case \"lessThanColumn\": {\n const left = resolveColumnRef(filter.column);\n const right = resolveColumnRef(filter.rhs);\n if (filter.minDiff !== undefined && filter.minDiff !== 0) {\n return {\n type: \"numericComparison\",\n operand: \"lt\",\n left: {\n type: \"numericBinary\",\n operand: \"add\",\n left,\n right: { type: \"constant\", value: filter.minDiff },\n },\n right,\n };\n }\n return { type: \"numericComparison\", operand: \"lt\", left, right };\n }\n case \"greaterThanColumn\": {\n const left = resolveColumnRef(filter.column);\n const right = resolveColumnRef(filter.rhs);\n if (filter.minDiff !== undefined && filter.minDiff !== 0) {\n return {\n type: \"numericComparison\",\n operand: \"gt\",\n left: {\n type: \"numericBinary\",\n operand: \"add\",\n left,\n right: { type: \"constant\", value: filter.minDiff },\n },\n right,\n };\n }\n return { type: \"numericComparison\", operand: \"gt\", left, right };\n }\n case \"lessThanColumnOrEqual\": {\n const left = resolveColumnRef(filter.column);\n const right = resolveColumnRef(filter.rhs);\n if (filter.minDiff !== undefined && filter.minDiff !== 0) {\n return {\n type: \"numericComparison\",\n operand: \"le\",\n left: {\n type: \"numericBinary\",\n operand: \"add\",\n left,\n right: { type: \"constant\", value: filter.minDiff },\n },\n right,\n };\n }\n return { type: \"numericComparison\", operand: \"le\", left, right };\n }\n case \"greaterThanColumnOrEqual\": {\n const left = resolveColumnRef(filter.column);\n const right = resolveColumnRef(filter.rhs);\n if (filter.minDiff !== undefined && filter.minDiff !== 0) {\n return {\n type: \"numericComparison\",\n operand: \"ge\",\n left: {\n type: \"numericBinary\",\n operand: \"add\",\n left,\n right: { type: \"constant\", value: filter.minDiff },\n },\n right,\n };\n }\n return { type: \"numericComparison\", operand: \"ge\", left, right };\n }\n\n case \"inSet\":\n return {\n type: \"isIn\",\n input: resolveColumnRef(filter.column),\n set: filter.value,\n };\n case \"notInSet\":\n return {\n type: \"not\",\n input: {\n type: \"isIn\",\n input: resolveColumnRef(filter.column),\n set: filter.value,\n },\n };\n\n case \"isNA\":\n return {\n type: \"isNull\",\n input: resolveColumnRef(filter.column),\n };\n case \"isNotNA\":\n return {\n type: \"not\",\n input: {\n type: \"isNull\",\n input: resolveColumnRef(filter.column),\n },\n };\n\n case \"ifNa\":\n return {\n type: \"ifNull\",\n input: resolveColumnRef(filter.column),\n replacement: { type: \"constant\", value: filter.replacement },\n };\n\n case \"topN\":\n case \"bottomN\":\n throw new Error(`Filter type \"${filter.type}\" is not supported in query expressions`);\n\n case undefined:\n throw new Error(\"Filter type is undefined\");\n\n default:\n assertNever(filter);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distill.cjs","sources":["../../src/filters/distill.ts"],"sourcesContent":["import { DistributiveKeys, UnionToTuples } from \"@milaboratories/helpers\";\nimport {
|
|
1
|
+
{"version":3,"file":"distill.cjs","sources":["../../src/filters/distill.ts"],"sourcesContent":["import { DistributiveKeys, UnionToTuples } from \"@milaboratories/helpers\";\nimport {\n RootFilterSpec,\n type FilterSpec,\n type FilterSpecLeaf,\n} from \"@milaboratories/pl-model-common\";\nimport { traverseFilterSpec } from \"./traverse\";\nimport { InferFilterSpecLeaf } from \"@milaboratories/pl-model-common\";\n\n/** All possible field names that can appear in any FilterSpecLeaf variant. */\ntype FilterSpecLeafKey = DistributiveKeys<FilterSpecLeaf<string>>;\n\n/** Compile-time check: every key in the tuple is a valid leaf key (via satisfies). */\nconst KNOWN_LEAF_KEYS_TUPLE: UnionToTuples<FilterSpecLeafKey> = [\n \"n\",\n \"x\",\n \"rhs\",\n \"type\",\n \"value\",\n \"column\",\n \"minDiff\",\n \"maxEdits\",\n \"wildcard\",\n \"replacement\",\n \"substitutionsOnly\",\n];\nconst KNOWN_LEAF_KEYS: Set<FilterSpecLeafKey> = new Set(KNOWN_LEAF_KEYS_TUPLE);\n\n/** Returns true if the leaf is filled — type is defined and no required fields are undefined. */\nfunction isFilledLeaf(node: Record<string, unknown>): boolean {\n if (node.type == null) return false;\n return !Object.values(node).some((v) => v === undefined);\n}\n\nfunction distillLeaf(node: Record<string, unknown>): FilterSpecLeaf<string> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n if (KNOWN_LEAF_KEYS.has(key as FilterSpecLeafKey)) {\n result[key] = value;\n }\n }\n return result as FilterSpecLeaf<string>;\n}\n\n/**\n * Strips non-FilterSpec metadata (whitelist approach) and removes\n * unfilled leaves (type is undefined or any required field is undefined).\n */\nexport function distillFilterSpec<\n FS extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>,\n R extends FS extends RootFilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>\n ? RootFilterSpec<InferFilterSpecLeaf<FS>>\n : FilterSpec<InferFilterSpecLeaf<FS>>,\n>(filter: null | undefined | FS): null | R {\n if (filter == null) return null;\n return traverseFilterSpec<FS, null | R>(filter, {\n leaf: (leaf) => {\n if (!isFilledLeaf(leaf as Record<string, unknown>)) return null;\n return distillLeaf(leaf as Record<string, unknown>) as R;\n },\n and: (results) => {\n const filtered = results.filter((f): f is NonNullable<typeof f> => f !== null);\n return filtered.length === 0 ? null : ({ type: \"and\", filters: filtered } as R);\n },\n or: (results) => {\n const filtered = results.filter((f): f is NonNullable<typeof f> => f !== null);\n return filtered.length === 0 ? null : ({ type: \"or\", filters: filtered } as R);\n },\n not: (result) => (result === null ? null : ({ type: \"not\", filter: result } as R)),\n });\n}\n"],"names":["traverseFilterSpec"],"mappings":";;;;AAYA;AACA,MAAM,qBAAqB,GAAqC;IAC9D,GAAG;IACH,GAAG;IACH,KAAK;IACL,MAAM;IACN,OAAO;IACP,QAAQ;IACR,SAAS;IACT,UAAU;IACV,UAAU;IACV,aAAa;IACb,mBAAmB;CACpB;AACD,MAAM,eAAe,GAA2B,IAAI,GAAG,CAAC,qBAAqB,CAAC;AAE9E;AACA,SAAS,YAAY,CAAC,IAA6B,EAAA;AACjD,IAAA,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;AAAE,QAAA,OAAO,KAAK;AACnC,IAAA,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;AAC1D;AAEA,SAAS,WAAW,CAAC,IAA6B,EAAA;IAChD,MAAM,MAAM,GAA4B,EAAE;AAC1C,IAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AAC/C,QAAA,IAAI,eAAe,CAAC,GAAG,CAAC,GAAwB,CAAC,EAAE;AACjD,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK;QACrB;IACF;AACA,IAAA,OAAO,MAAgC;AACzC;AAEA;;;AAGG;AACG,SAAU,iBAAiB,CAK/B,MAA6B,EAAA;IAC7B,IAAI,MAAM,IAAI,IAAI;AAAE,QAAA,OAAO,IAAI;IAC/B,OAAOA,2BAAkB,CAAe,MAAM,EAAE;AAC9C,QAAA,IAAI,EAAE,CAAC,IAAI,KAAI;AACb,YAAA,IAAI,CAAC,YAAY,CAAC,IAA+B,CAAC;AAAE,gBAAA,OAAO,IAAI;AAC/D,YAAA,OAAO,WAAW,CAAC,IAA+B,CAAM;QAC1D,CAAC;AACD,QAAA,GAAG,EAAE,CAAC,OAAO,KAAI;AACf,YAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAiC,CAAC,KAAK,IAAI,CAAC;YAC9E,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,GAAG,IAAI,GAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAQ;QACjF,CAAC;AACD,QAAA,EAAE,EAAE,CAAC,OAAO,KAAI;AACd,YAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAiC,CAAC,KAAK,IAAI,CAAC;YAC9E,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,GAAG,IAAI,GAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAQ;QAChF,CAAC;QACD,GAAG,EAAE,CAAC,MAAM,MAAM,MAAM,KAAK,IAAI,GAAG,IAAI,GAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAQ,CAAC;AACnF,KAAA,CAAC;AACJ;;;;"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
|
-
import { type FilterSpec, type FilterSpecLeaf } from "@milaboratories/pl-model-common";
|
|
1
|
+
import { RootFilterSpec, type FilterSpec, type FilterSpecLeaf } from "@milaboratories/pl-model-common";
|
|
2
|
+
import { InferFilterSpecLeaf } from "@milaboratories/pl-model-common";
|
|
2
3
|
/**
|
|
3
4
|
* Strips non-FilterSpec metadata (whitelist approach) and removes
|
|
4
5
|
* unfilled leaves (type is undefined or any required field is undefined).
|
|
5
6
|
*/
|
|
6
|
-
export declare function distillFilterSpec<
|
|
7
|
+
export declare function distillFilterSpec<FS extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>, R extends FS extends RootFilterSpec<FilterSpecLeaf<unknown>, unknown, unknown> ? RootFilterSpec<InferFilterSpecLeaf<FS>> : FilterSpec<InferFilterSpecLeaf<FS>>>(filter: null | undefined | FS): null | R;
|
|
7
8
|
//# sourceMappingURL=distill.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distill.d.ts","sourceRoot":"","sources":["../../src/filters/distill.ts"],"names":[],"mappings":"AACA,OAAO,
|
|
1
|
+
{"version":3,"file":"distill.d.ts","sourceRoot":"","sources":["../../src/filters/distill.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EACd,KAAK,UAAU,EACf,KAAK,cAAc,EACpB,MAAM,iCAAiC,CAAC;AAEzC,OAAO,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAqCtE;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,EAAE,SAAS,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAChE,CAAC,SAAS,EAAE,SAAS,cAAc,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,GAC1E,cAAc,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,GACvC,UAAU,CAAC,mBAAmB,CAAC,EAAE,CAAC,CAAC,EACvC,MAAM,EAAE,IAAI,GAAG,SAAS,GAAG,EAAE,GAAG,IAAI,GAAG,CAAC,CAiBzC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"distill.js","sources":["../../src/filters/distill.ts"],"sourcesContent":["import { DistributiveKeys, UnionToTuples } from \"@milaboratories/helpers\";\nimport {
|
|
1
|
+
{"version":3,"file":"distill.js","sources":["../../src/filters/distill.ts"],"sourcesContent":["import { DistributiveKeys, UnionToTuples } from \"@milaboratories/helpers\";\nimport {\n RootFilterSpec,\n type FilterSpec,\n type FilterSpecLeaf,\n} from \"@milaboratories/pl-model-common\";\nimport { traverseFilterSpec } from \"./traverse\";\nimport { InferFilterSpecLeaf } from \"@milaboratories/pl-model-common\";\n\n/** All possible field names that can appear in any FilterSpecLeaf variant. */\ntype FilterSpecLeafKey = DistributiveKeys<FilterSpecLeaf<string>>;\n\n/** Compile-time check: every key in the tuple is a valid leaf key (via satisfies). */\nconst KNOWN_LEAF_KEYS_TUPLE: UnionToTuples<FilterSpecLeafKey> = [\n \"n\",\n \"x\",\n \"rhs\",\n \"type\",\n \"value\",\n \"column\",\n \"minDiff\",\n \"maxEdits\",\n \"wildcard\",\n \"replacement\",\n \"substitutionsOnly\",\n];\nconst KNOWN_LEAF_KEYS: Set<FilterSpecLeafKey> = new Set(KNOWN_LEAF_KEYS_TUPLE);\n\n/** Returns true if the leaf is filled — type is defined and no required fields are undefined. */\nfunction isFilledLeaf(node: Record<string, unknown>): boolean {\n if (node.type == null) return false;\n return !Object.values(node).some((v) => v === undefined);\n}\n\nfunction distillLeaf(node: Record<string, unknown>): FilterSpecLeaf<string> {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(node)) {\n if (KNOWN_LEAF_KEYS.has(key as FilterSpecLeafKey)) {\n result[key] = value;\n }\n }\n return result as FilterSpecLeaf<string>;\n}\n\n/**\n * Strips non-FilterSpec metadata (whitelist approach) and removes\n * unfilled leaves (type is undefined or any required field is undefined).\n */\nexport function distillFilterSpec<\n FS extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>,\n R extends FS extends RootFilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>\n ? RootFilterSpec<InferFilterSpecLeaf<FS>>\n : FilterSpec<InferFilterSpecLeaf<FS>>,\n>(filter: null | undefined | FS): null | R {\n if (filter == null) return null;\n return traverseFilterSpec<FS, null | R>(filter, {\n leaf: (leaf) => {\n if (!isFilledLeaf(leaf as Record<string, unknown>)) return null;\n return distillLeaf(leaf as Record<string, unknown>) as R;\n },\n and: (results) => {\n const filtered = results.filter((f): f is NonNullable<typeof f> => f !== null);\n return filtered.length === 0 ? null : ({ type: \"and\", filters: filtered } as R);\n },\n or: (results) => {\n const filtered = results.filter((f): f is NonNullable<typeof f> => f !== null);\n return filtered.length === 0 ? null : ({ type: \"or\", filters: filtered } as R);\n },\n not: (result) => (result === null ? null : ({ type: \"not\", filter: result } as R)),\n });\n}\n"],"names":[],"mappings":";;AAYA;AACA,MAAM,qBAAqB,GAAqC;IAC9D,GAAG;IACH,GAAG;IACH,KAAK;IACL,MAAM;IACN,OAAO;IACP,QAAQ;IACR,SAAS;IACT,UAAU;IACV,UAAU;IACV,aAAa;IACb,mBAAmB;CACpB;AACD,MAAM,eAAe,GAA2B,IAAI,GAAG,CAAC,qBAAqB,CAAC;AAE9E;AACA,SAAS,YAAY,CAAC,IAA6B,EAAA;AACjD,IAAA,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI;AAAE,QAAA,OAAO,KAAK;AACnC,IAAA,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;AAC1D;AAEA,SAAS,WAAW,CAAC,IAA6B,EAAA;IAChD,MAAM,MAAM,GAA4B,EAAE;AAC1C,IAAA,KAAK,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;AAC/C,QAAA,IAAI,eAAe,CAAC,GAAG,CAAC,GAAwB,CAAC,EAAE;AACjD,YAAA,MAAM,CAAC,GAAG,CAAC,GAAG,KAAK;QACrB;IACF;AACA,IAAA,OAAO,MAAgC;AACzC;AAEA;;;AAGG;AACG,SAAU,iBAAiB,CAK/B,MAA6B,EAAA;IAC7B,IAAI,MAAM,IAAI,IAAI;AAAE,QAAA,OAAO,IAAI;IAC/B,OAAO,kBAAkB,CAAe,MAAM,EAAE;AAC9C,QAAA,IAAI,EAAE,CAAC,IAAI,KAAI;AACb,YAAA,IAAI,CAAC,YAAY,CAAC,IAA+B,CAAC;AAAE,gBAAA,OAAO,IAAI;AAC/D,YAAA,OAAO,WAAW,CAAC,IAA+B,CAAM;QAC1D,CAAC;AACD,QAAA,GAAG,EAAE,CAAC,OAAO,KAAI;AACf,YAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAiC,CAAC,KAAK,IAAI,CAAC;YAC9E,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,GAAG,IAAI,GAAI,EAAE,IAAI,EAAE,KAAK,EAAE,OAAO,EAAE,QAAQ,EAAQ;QACjF,CAAC;AACD,QAAA,EAAE,EAAE,CAAC,OAAO,KAAI;AACd,YAAA,MAAM,QAAQ,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,KAAiC,CAAC,KAAK,IAAI,CAAC;YAC9E,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,GAAG,IAAI,GAAI,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,QAAQ,EAAQ;QAChF,CAAC;QACD,GAAG,EAAE,CAAC,MAAM,MAAM,MAAM,KAAK,IAAI,GAAG,IAAI,GAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,MAAM,EAAQ,CAAC;AACnF,KAAA,CAAC;AACJ;;;;"}
|
|
@@ -12,17 +12,21 @@
|
|
|
12
12
|
* 3. For leaf nodes, call `leaf` directly
|
|
13
13
|
*/
|
|
14
14
|
function traverseFilterSpec(filter, visitor) {
|
|
15
|
+
return traverseFilterSpecImpl(filter, visitor);
|
|
16
|
+
}
|
|
17
|
+
/** Internal implementation with simple generics for clean recursion. */
|
|
18
|
+
function traverseFilterSpecImpl(filter, visitor) {
|
|
15
19
|
switch (filter.type) {
|
|
16
20
|
case "and":
|
|
17
21
|
return visitor.and(filter.filters
|
|
18
22
|
.filter((f) => f.type !== undefined)
|
|
19
|
-
.map((f) =>
|
|
23
|
+
.map((f) => traverseFilterSpecImpl(f, visitor)));
|
|
20
24
|
case "or":
|
|
21
25
|
return visitor.or(filter.filters
|
|
22
26
|
.filter((f) => f.type !== undefined)
|
|
23
|
-
.map((f) =>
|
|
27
|
+
.map((f) => traverseFilterSpecImpl(f, visitor)));
|
|
24
28
|
case "not":
|
|
25
|
-
return visitor.not(
|
|
29
|
+
return visitor.not(traverseFilterSpecImpl(filter.filter, visitor));
|
|
26
30
|
default:
|
|
27
31
|
return visitor.leaf(filter);
|
|
28
32
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traverse.cjs","sources":["../../src/filters/traverse.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"traverse.cjs","sources":["../../src/filters/traverse.ts"],"sourcesContent":["import type {\n FilterSpec,\n FilterSpecLeaf,\n FilterSpecNode,\n InferFilterSpecLeafColumn,\n} from \"@milaboratories/pl-model-common\";\nimport type {\n InferFilterSpecCommonLeaf,\n InferFilterSpecLeaf,\n} from \"@milaboratories/pl-model-common\";\n\nexport type FilterSpecVisitor<LeafArg, R> = {\n /** Handle a leaf filter node. */\n leaf: (leaf: LeafArg) => R;\n /** Handle an AND node after children have been traversed. */\n and: (results: R[]) => R;\n /** Handle an OR node after children have been traversed. */\n or: (results: R[]) => R;\n /** Handle a NOT node after the inner filter has been traversed. */\n not: (result: R) => R;\n};\n\n/**\n * Recursively traverses a FilterSpec tree bottom-up, applying visitor callbacks.\n *\n * Entries with `{ type: undefined }` inside `and`/`or` arrays are skipped\n * (these represent unfilled filter slots in the UI).\n *\n * Traversal order:\n * 1. Recurse into child filters (`and`/`or`/`not`)\n * 2. Apply the corresponding visitor callback with already-traversed children\n * 3. For leaf nodes, call `leaf` directly\n */\nexport function traverseFilterSpec<\n F extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>,\n R,\n>(\n filter: F,\n visitor: FilterSpecVisitor<InferFilterSpecCommonLeaf<F> & InferFilterSpecLeaf<F>, R>,\n): R {\n return traverseFilterSpecImpl(filter, visitor as FilterSpecVisitor<unknown, R>);\n}\n/** Internal implementation with simple generics for clean recursion. */\nfunction traverseFilterSpecImpl<R>(\n filter: FilterSpecNode<FilterSpecLeaf<unknown>, unknown, unknown>,\n visitor: FilterSpecVisitor<unknown, R>,\n): R {\n switch (filter.type) {\n case \"and\":\n return visitor.and(\n filter.filters\n .filter((f) => f.type !== undefined)\n .map((f) => traverseFilterSpecImpl(f, visitor)),\n );\n case \"or\":\n return visitor.or(\n filter.filters\n .filter((f) => f.type !== undefined)\n .map((f) => traverseFilterSpecImpl(f, visitor)),\n );\n case \"not\":\n return visitor.not(traverseFilterSpecImpl(filter.filter, visitor));\n default:\n return visitor.leaf(filter);\n }\n}\n\n/** Collects all column references (`column` and `rhs` fields) from filter leaves. */\nexport function collectFilterSpecColumns<\n F extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>,\n R extends InferFilterSpecLeafColumn<F> = InferFilterSpecLeafColumn<F>,\n>(filter: F): R[] {\n return traverseFilterSpec(filter, {\n leaf: (leaf) => {\n const cols: R[] = [];\n if (\"column\" in leaf && leaf.column !== undefined) cols.push(leaf.column as R);\n if (\"rhs\" in leaf && leaf.rhs !== undefined) cols.push(leaf.rhs as R);\n return cols;\n },\n and: (results) => results.flat(),\n or: (results) => results.flat(),\n not: (result) => result,\n });\n}\n"],"names":[],"mappings":";;AAsBA;;;;;;;;;;AAUG;AACG,SAAU,kBAAkB,CAIhC,MAAS,EACT,OAAoF,EAAA;AAEpF,IAAA,OAAO,sBAAsB,CAAC,MAAM,EAAE,OAAwC,CAAC;AACjF;AACA;AACA,SAAS,sBAAsB,CAC7B,MAAiE,EACjE,OAAsC,EAAA;AAEtC,IAAA,QAAQ,MAAM,CAAC,IAAI;AACjB,QAAA,KAAK,KAAK;AACR,YAAA,OAAO,OAAO,CAAC,GAAG,CAChB,MAAM,CAAC;iBACJ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,SAAS;AAClC,iBAAA,GAAG,CAAC,CAAC,CAAC,KAAK,sBAAsB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAClD;AACH,QAAA,KAAK,IAAI;AACP,YAAA,OAAO,OAAO,CAAC,EAAE,CACf,MAAM,CAAC;iBACJ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,SAAS;AAClC,iBAAA,GAAG,CAAC,CAAC,CAAC,KAAK,sBAAsB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAClD;AACH,QAAA,KAAK,KAAK;AACR,YAAA,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACpE,QAAA;AACE,YAAA,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;;AAEjC;AAEA;AACM,SAAU,wBAAwB,CAGtC,MAAS,EAAA;IACT,OAAO,kBAAkB,CAAC,MAAM,EAAE;AAChC,QAAA,IAAI,EAAE,CAAC,IAAI,KAAI;YACb,MAAM,IAAI,GAAQ,EAAE;YACpB,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;AAAE,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAW,CAAC;YAC9E,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;AAAE,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAQ,CAAC;AACrE,YAAA,OAAO,IAAI;QACb,CAAC;QACD,GAAG,EAAE,CAAC,OAAO,KAAK,OAAO,CAAC,IAAI,EAAE;QAChC,EAAE,EAAE,CAAC,OAAO,KAAK,OAAO,CAAC,IAAI,EAAE;AAC/B,QAAA,GAAG,EAAE,CAAC,MAAM,KAAK,MAAM;AACxB,KAAA,CAAC;AACJ;;;;;"}
|
|
@@ -1,4 +1,15 @@
|
|
|
1
|
-
import type { FilterSpecLeaf,
|
|
1
|
+
import type { FilterSpec, FilterSpecLeaf, InferFilterSpecLeafColumn } from "@milaboratories/pl-model-common";
|
|
2
|
+
import type { InferFilterSpecCommonLeaf, InferFilterSpecLeaf } from "@milaboratories/pl-model-common";
|
|
3
|
+
export type FilterSpecVisitor<LeafArg, R> = {
|
|
4
|
+
/** Handle a leaf filter node. */
|
|
5
|
+
leaf: (leaf: LeafArg) => R;
|
|
6
|
+
/** Handle an AND node after children have been traversed. */
|
|
7
|
+
and: (results: R[]) => R;
|
|
8
|
+
/** Handle an OR node after children have been traversed. */
|
|
9
|
+
or: (results: R[]) => R;
|
|
10
|
+
/** Handle a NOT node after the inner filter has been traversed. */
|
|
11
|
+
not: (result: R) => R;
|
|
12
|
+
};
|
|
2
13
|
/**
|
|
3
14
|
* Recursively traverses a FilterSpec tree bottom-up, applying visitor callbacks.
|
|
4
15
|
*
|
|
@@ -10,16 +21,7 @@ import type { FilterSpecLeaf, FilterSpecNode } from "@milaboratories/pl-model-co
|
|
|
10
21
|
* 2. Apply the corresponding visitor callback with already-traversed children
|
|
11
22
|
* 3. For leaf nodes, call `leaf` directly
|
|
12
23
|
*/
|
|
13
|
-
export declare function traverseFilterSpec<
|
|
14
|
-
/** Handle a leaf filter node. */
|
|
15
|
-
leaf: (leaf: CommonLeaf & Leaf) => R;
|
|
16
|
-
/** Handle an AND node after children have been traversed. */
|
|
17
|
-
and: (results: R[]) => R;
|
|
18
|
-
/** Handle an OR node after children have been traversed. */
|
|
19
|
-
or: (results: R[]) => R;
|
|
20
|
-
/** Handle a NOT node after the inner filter has been traversed. */
|
|
21
|
-
not: (result: R) => R;
|
|
22
|
-
}): R;
|
|
24
|
+
export declare function traverseFilterSpec<F extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>, R>(filter: F, visitor: FilterSpecVisitor<InferFilterSpecCommonLeaf<F> & InferFilterSpecLeaf<F>, R>): R;
|
|
23
25
|
/** Collects all column references (`column` and `rhs` fields) from filter leaves. */
|
|
24
|
-
export declare function collectFilterSpecColumns<
|
|
26
|
+
export declare function collectFilterSpecColumns<F extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>, R extends InferFilterSpecLeafColumn<F> = InferFilterSpecLeafColumn<F>>(filter: F): R[];
|
|
25
27
|
//# sourceMappingURL=traverse.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traverse.d.ts","sourceRoot":"","sources":["../../src/filters/traverse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"traverse.d.ts","sourceRoot":"","sources":["../../src/filters/traverse.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EAEd,yBAAyB,EAC1B,MAAM,iCAAiC,CAAC;AACzC,OAAO,KAAK,EACV,yBAAyB,EACzB,mBAAmB,EACpB,MAAM,iCAAiC,CAAC;AAEzC,MAAM,MAAM,iBAAiB,CAAC,OAAO,EAAE,CAAC,IAAI;IAC1C,iCAAiC;IACjC,IAAI,EAAE,CAAC,IAAI,EAAE,OAAO,KAAK,CAAC,CAAC;IAC3B,6DAA6D;IAC7D,GAAG,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACzB,4DAA4D;IAC5D,EAAE,EAAE,CAAC,OAAO,EAAE,CAAC,EAAE,KAAK,CAAC,CAAC;IACxB,mEAAmE;IACnE,GAAG,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,CAAC,CAAC;CACvB,CAAC;AAEF;;;;;;;;;;GAUG;AACH,wBAAgB,kBAAkB,CAChC,CAAC,SAAS,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAC/D,CAAC,EAED,MAAM,EAAE,CAAC,EACT,OAAO,EAAE,iBAAiB,CAAC,yBAAyB,CAAC,CAAC,CAAC,GAAG,mBAAmB,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,GACnF,CAAC,CAEH;AA0BD,qFAAqF;AACrF,wBAAgB,wBAAwB,CACtC,CAAC,SAAS,UAAU,CAAC,cAAc,CAAC,OAAO,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAC/D,CAAC,SAAS,yBAAyB,CAAC,CAAC,CAAC,GAAG,yBAAyB,CAAC,CAAC,CAAC,EACrE,MAAM,EAAE,CAAC,GAAG,CAAC,EAAE,CAYhB"}
|
package/dist/filters/traverse.js
CHANGED
|
@@ -10,17 +10,21 @@
|
|
|
10
10
|
* 3. For leaf nodes, call `leaf` directly
|
|
11
11
|
*/
|
|
12
12
|
function traverseFilterSpec(filter, visitor) {
|
|
13
|
+
return traverseFilterSpecImpl(filter, visitor);
|
|
14
|
+
}
|
|
15
|
+
/** Internal implementation with simple generics for clean recursion. */
|
|
16
|
+
function traverseFilterSpecImpl(filter, visitor) {
|
|
13
17
|
switch (filter.type) {
|
|
14
18
|
case "and":
|
|
15
19
|
return visitor.and(filter.filters
|
|
16
20
|
.filter((f) => f.type !== undefined)
|
|
17
|
-
.map((f) =>
|
|
21
|
+
.map((f) => traverseFilterSpecImpl(f, visitor)));
|
|
18
22
|
case "or":
|
|
19
23
|
return visitor.or(filter.filters
|
|
20
24
|
.filter((f) => f.type !== undefined)
|
|
21
|
-
.map((f) =>
|
|
25
|
+
.map((f) => traverseFilterSpecImpl(f, visitor)));
|
|
22
26
|
case "not":
|
|
23
|
-
return visitor.not(
|
|
27
|
+
return visitor.not(traverseFilterSpecImpl(filter.filter, visitor));
|
|
24
28
|
default:
|
|
25
29
|
return visitor.leaf(filter);
|
|
26
30
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"traverse.js","sources":["../../src/filters/traverse.ts"],"sourcesContent":["import type {
|
|
1
|
+
{"version":3,"file":"traverse.js","sources":["../../src/filters/traverse.ts"],"sourcesContent":["import type {\n FilterSpec,\n FilterSpecLeaf,\n FilterSpecNode,\n InferFilterSpecLeafColumn,\n} from \"@milaboratories/pl-model-common\";\nimport type {\n InferFilterSpecCommonLeaf,\n InferFilterSpecLeaf,\n} from \"@milaboratories/pl-model-common\";\n\nexport type FilterSpecVisitor<LeafArg, R> = {\n /** Handle a leaf filter node. */\n leaf: (leaf: LeafArg) => R;\n /** Handle an AND node after children have been traversed. */\n and: (results: R[]) => R;\n /** Handle an OR node after children have been traversed. */\n or: (results: R[]) => R;\n /** Handle a NOT node after the inner filter has been traversed. */\n not: (result: R) => R;\n};\n\n/**\n * Recursively traverses a FilterSpec tree bottom-up, applying visitor callbacks.\n *\n * Entries with `{ type: undefined }` inside `and`/`or` arrays are skipped\n * (these represent unfilled filter slots in the UI).\n *\n * Traversal order:\n * 1. Recurse into child filters (`and`/`or`/`not`)\n * 2. Apply the corresponding visitor callback with already-traversed children\n * 3. For leaf nodes, call `leaf` directly\n */\nexport function traverseFilterSpec<\n F extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>,\n R,\n>(\n filter: F,\n visitor: FilterSpecVisitor<InferFilterSpecCommonLeaf<F> & InferFilterSpecLeaf<F>, R>,\n): R {\n return traverseFilterSpecImpl(filter, visitor as FilterSpecVisitor<unknown, R>);\n}\n/** Internal implementation with simple generics for clean recursion. */\nfunction traverseFilterSpecImpl<R>(\n filter: FilterSpecNode<FilterSpecLeaf<unknown>, unknown, unknown>,\n visitor: FilterSpecVisitor<unknown, R>,\n): R {\n switch (filter.type) {\n case \"and\":\n return visitor.and(\n filter.filters\n .filter((f) => f.type !== undefined)\n .map((f) => traverseFilterSpecImpl(f, visitor)),\n );\n case \"or\":\n return visitor.or(\n filter.filters\n .filter((f) => f.type !== undefined)\n .map((f) => traverseFilterSpecImpl(f, visitor)),\n );\n case \"not\":\n return visitor.not(traverseFilterSpecImpl(filter.filter, visitor));\n default:\n return visitor.leaf(filter);\n }\n}\n\n/** Collects all column references (`column` and `rhs` fields) from filter leaves. */\nexport function collectFilterSpecColumns<\n F extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>,\n R extends InferFilterSpecLeafColumn<F> = InferFilterSpecLeafColumn<F>,\n>(filter: F): R[] {\n return traverseFilterSpec(filter, {\n leaf: (leaf) => {\n const cols: R[] = [];\n if (\"column\" in leaf && leaf.column !== undefined) cols.push(leaf.column as R);\n if (\"rhs\" in leaf && leaf.rhs !== undefined) cols.push(leaf.rhs as R);\n return cols;\n },\n and: (results) => results.flat(),\n or: (results) => results.flat(),\n not: (result) => result,\n });\n}\n"],"names":[],"mappings":"AAsBA;;;;;;;;;;AAUG;AACG,SAAU,kBAAkB,CAIhC,MAAS,EACT,OAAoF,EAAA;AAEpF,IAAA,OAAO,sBAAsB,CAAC,MAAM,EAAE,OAAwC,CAAC;AACjF;AACA;AACA,SAAS,sBAAsB,CAC7B,MAAiE,EACjE,OAAsC,EAAA;AAEtC,IAAA,QAAQ,MAAM,CAAC,IAAI;AACjB,QAAA,KAAK,KAAK;AACR,YAAA,OAAO,OAAO,CAAC,GAAG,CAChB,MAAM,CAAC;iBACJ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,SAAS;AAClC,iBAAA,GAAG,CAAC,CAAC,CAAC,KAAK,sBAAsB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAClD;AACH,QAAA,KAAK,IAAI;AACP,YAAA,OAAO,OAAO,CAAC,EAAE,CACf,MAAM,CAAC;iBACJ,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,SAAS;AAClC,iBAAA,GAAG,CAAC,CAAC,CAAC,KAAK,sBAAsB,CAAC,CAAC,EAAE,OAAO,CAAC,CAAC,CAClD;AACH,QAAA,KAAK,KAAK;AACR,YAAA,OAAO,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AACpE,QAAA;AACE,YAAA,OAAO,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC;;AAEjC;AAEA;AACM,SAAU,wBAAwB,CAGtC,MAAS,EAAA;IACT,OAAO,kBAAkB,CAAC,MAAM,EAAE;AAChC,QAAA,IAAI,EAAE,CAAC,IAAI,KAAI;YACb,MAAM,IAAI,GAAQ,EAAE;YACpB,IAAI,QAAQ,IAAI,IAAI,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS;AAAE,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,MAAW,CAAC;YAC9E,IAAI,KAAK,IAAI,IAAI,IAAI,IAAI,CAAC,GAAG,KAAK,SAAS;AAAE,gBAAA,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,GAAQ,CAAC;AACrE,YAAA,OAAO,IAAI;QACb,CAAC;QACD,GAAG,EAAE,CAAC,OAAO,KAAK,OAAO,CAAC,IAAI,EAAE;QAChC,EAAE,EAAE,CAAC,OAAO,KAAK,OAAO,CAAC,IAAI,EAAE;AAC/B,QAAA,GAAG,EAAE,CAAC,MAAM,KAAK,MAAM;AACxB,KAAA,CAAC;AACJ;;;;"}
|
package/dist/package.json.cjs
CHANGED
package/dist/package.json.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@platforma-sdk/model",
|
|
3
|
-
"version": "1.54.
|
|
3
|
+
"version": "1.54.13",
|
|
4
4
|
"description": "Platforma.bio SDK / Block Model",
|
|
5
5
|
"files": [
|
|
6
6
|
"./dist/**/*",
|
|
@@ -24,19 +24,19 @@
|
|
|
24
24
|
"fast-json-patch": "^3.1.1",
|
|
25
25
|
"utility-types": "^3.11.0",
|
|
26
26
|
"zod": "~3.23.8",
|
|
27
|
-
"@milaboratories/helpers": "1.13.4",
|
|
28
27
|
"@milaboratories/pl-error-like": "1.12.8",
|
|
29
|
-
"@milaboratories/
|
|
30
|
-
"@milaboratories/
|
|
28
|
+
"@milaboratories/pl-model-common": "1.24.11",
|
|
29
|
+
"@milaboratories/helpers": "1.13.5",
|
|
30
|
+
"@milaboratories/ptabler-expression-js": "1.1.21"
|
|
31
31
|
},
|
|
32
32
|
"devDependencies": {
|
|
33
33
|
"@vitest/coverage-istanbul": "^4.0.16",
|
|
34
34
|
"fast-json-patch": "^3.1.1",
|
|
35
35
|
"typescript": "~5.6.3",
|
|
36
36
|
"vitest": "^4.0.16",
|
|
37
|
+
"@milaboratories/ts-configs": "1.2.1",
|
|
37
38
|
"@milaboratories/ts-builder": "1.2.10",
|
|
38
|
-
"@milaboratories/build-configs": "1.4.4"
|
|
39
|
-
"@milaboratories/ts-configs": "1.2.1"
|
|
39
|
+
"@milaboratories/build-configs": "1.4.4"
|
|
40
40
|
},
|
|
41
41
|
"scripts": {
|
|
42
42
|
"build": "ts-builder build --target node",
|
|
@@ -158,10 +158,10 @@ function migrateV4toV5(
|
|
|
158
158
|
const nextId = () => ++idCounter;
|
|
159
159
|
|
|
160
160
|
const migratedCache: PlDataTableStateV2CacheEntry[] = state.stateCache.map((entry) => {
|
|
161
|
-
const leaves: PlDataTableFiltersWithMeta[] = [];
|
|
161
|
+
const leaves: PlDataTableFiltersWithMeta["filters"] = [];
|
|
162
162
|
for (const f of entry.filtersState) {
|
|
163
163
|
if (f.filter !== null && !f.filter.disabled) {
|
|
164
|
-
const column = canonicalizeJson
|
|
164
|
+
const column = canonicalizeJson(f.id);
|
|
165
165
|
leaves.push(migrateTableFilter(column, f.filter.value, nextId));
|
|
166
166
|
}
|
|
167
167
|
}
|
|
@@ -198,10 +198,10 @@ function migrateV4toV5(
|
|
|
198
198
|
|
|
199
199
|
/** Migrate a single per-column PlTableFilter to a tree-based FilterSpec node */
|
|
200
200
|
function migrateTableFilter(
|
|
201
|
-
column:
|
|
201
|
+
column: CanonicalizedJson<PTableColumnId>,
|
|
202
202
|
filter: PlTableFilter,
|
|
203
203
|
nextId: () => number,
|
|
204
|
-
): PlDataTableFiltersWithMeta {
|
|
204
|
+
): PlDataTableFiltersWithMeta["filters"][number] {
|
|
205
205
|
const id = nextId();
|
|
206
206
|
switch (filter.type) {
|
|
207
207
|
case "isNA":
|
|
@@ -26,6 +26,7 @@ import {
|
|
|
26
26
|
readAnnotation,
|
|
27
27
|
uniqueBy,
|
|
28
28
|
isBooleanExpression,
|
|
29
|
+
parseJson,
|
|
29
30
|
} from "@milaboratories/pl-model-common";
|
|
30
31
|
import { filterSpecToSpecQueryExpr } from "../../filters";
|
|
31
32
|
import type { RenderCtxBase, TreeNodeAccessor, PColumnDataUniversal } from "../../render";
|
|
@@ -186,7 +187,7 @@ export function createPlDataTableV2<A, U>(
|
|
|
186
187
|
const stateFilters = tableStateNormalized.pTableParams.filters;
|
|
187
188
|
const opsFilters = ops?.filters ?? null;
|
|
188
189
|
const filters: null | PlDataTableFilters =
|
|
189
|
-
stateFilters
|
|
190
|
+
stateFilters != null && opsFilters != null
|
|
190
191
|
? { type: "and", filters: [stateFilters, opsFilters] }
|
|
191
192
|
: (stateFilters ?? opsFilters);
|
|
192
193
|
const filterColumns = filters ? collectFilterSpecColumns(filters) : [];
|
|
@@ -218,6 +219,7 @@ export function createPlDataTableV2<A, U>(
|
|
|
218
219
|
sorting,
|
|
219
220
|
coreColumnPredicate: ops?.coreColumnPredicate,
|
|
220
221
|
});
|
|
222
|
+
|
|
221
223
|
const fullHandle = ctx.createPTableV2(fullDef);
|
|
222
224
|
if (!fullHandle) return undefined;
|
|
223
225
|
|
|
@@ -245,12 +247,22 @@ export function createPlDataTableV2<A, U>(
|
|
|
245
247
|
coreColumns.forEach((c) => hiddenColumns.delete(c));
|
|
246
248
|
}
|
|
247
249
|
|
|
248
|
-
//
|
|
250
|
+
// Preserve sorted columns from being hidden
|
|
249
251
|
sorting
|
|
250
252
|
.map((s) => s.column)
|
|
251
253
|
.filter((c): c is PTableColumnIdColumn => c.type === "column")
|
|
252
254
|
.forEach((c) => hiddenColumns.delete(c.id));
|
|
253
255
|
|
|
256
|
+
// Preserve filter columns from being hidden
|
|
257
|
+
if (filters) {
|
|
258
|
+
collectFilterSpecColumns(filters)
|
|
259
|
+
.flatMap((c) => {
|
|
260
|
+
const obj = parseJson(c);
|
|
261
|
+
return obj.type === "column" ? [obj.id] : [];
|
|
262
|
+
})
|
|
263
|
+
.forEach((c) => hiddenColumns.delete(c));
|
|
264
|
+
}
|
|
265
|
+
|
|
254
266
|
const visibleColumns = columns.filter((c) => !hiddenColumns.has(c.id));
|
|
255
267
|
const visibleLabelColumns = getMatchingLabelColumns(
|
|
256
268
|
visibleColumns.map(getColumnIdAndSpec),
|
|
@@ -269,13 +281,14 @@ export function createPlDataTableV2<A, U>(
|
|
|
269
281
|
coreColumnPredicate,
|
|
270
282
|
});
|
|
271
283
|
const visibleHandle = ctx.createPTableV2(visibleDef);
|
|
284
|
+
|
|
272
285
|
if (!visibleHandle) return undefined;
|
|
273
286
|
|
|
274
287
|
return {
|
|
275
288
|
sourceId: tableStateNormalized.pTableParams.sourceId,
|
|
276
289
|
fullTableHandle: fullHandle,
|
|
277
290
|
visibleTableHandle: visibleHandle,
|
|
278
|
-
}
|
|
291
|
+
} as PlDataTableModel;
|
|
279
292
|
}
|
|
280
293
|
|
|
281
294
|
/** Create sheet entries for PlDataTable */
|
|
@@ -8,8 +8,10 @@ import type {
|
|
|
8
8
|
PTableSorting,
|
|
9
9
|
PColumnIdAndSpec,
|
|
10
10
|
PTableHandle,
|
|
11
|
+
RootFilterSpec,
|
|
12
|
+
PTableColumnId,
|
|
11
13
|
} from "@milaboratories/pl-model-common";
|
|
12
|
-
import type {
|
|
14
|
+
import type { FilterSpecLeaf } from "../../filters";
|
|
13
15
|
|
|
14
16
|
export type PlTableColumnId = {
|
|
15
17
|
/** Original column spec */
|
|
@@ -60,10 +62,10 @@ export type PlDataTableSheetState = {
|
|
|
60
62
|
};
|
|
61
63
|
|
|
62
64
|
/** Tree-based filter state compatible with PlAdvancedFilter's RootFilter */
|
|
63
|
-
export type PlDataTableFilters =
|
|
64
|
-
export type PlDataTableFiltersWithMeta =
|
|
65
|
-
FilterSpecLeaf<
|
|
66
|
-
{ id: number; isExpanded?: boolean }
|
|
65
|
+
export type PlDataTableFilters = RootFilterSpec<FilterSpecLeaf<CanonicalizedJson<PTableColumnId>>>;
|
|
66
|
+
export type PlDataTableFiltersWithMeta = RootFilterSpec<
|
|
67
|
+
FilterSpecLeaf<CanonicalizedJson<PTableColumnId>>,
|
|
68
|
+
{ id: number; isExpanded?: boolean; source?: "table-filter" | "table-search" }
|
|
67
69
|
>;
|
|
68
70
|
|
|
69
71
|
export type PlDataTableStateV2CacheEntry = {
|
|
@@ -75,6 +77,8 @@ export type PlDataTableStateV2CacheEntry = {
|
|
|
75
77
|
sheetsState: PlDataTableSheetState[];
|
|
76
78
|
/** Filters state (tree-based, compatible with PlAdvancedFilter) */
|
|
77
79
|
filtersState: null | PlDataTableFiltersWithMeta;
|
|
80
|
+
/** Fast search string */
|
|
81
|
+
searchString?: string;
|
|
78
82
|
};
|
|
79
83
|
|
|
80
84
|
export type PTableParamsV2 =
|
|
@@ -11,15 +11,14 @@ import { traverseFilterSpec } from "../traverse";
|
|
|
11
11
|
/** Parses a CanonicalizedJson<PTableColumnId> string into a SpecQueryExpression reference. */
|
|
12
12
|
function resolveColumnRef(columnStr: string): SpecQueryExpression {
|
|
13
13
|
const parsed = JSON.parse(columnStr) as PTableColumnId;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return { type: "columnRef", value: parsed.id };
|
|
14
|
+
return parsed.type === "axis"
|
|
15
|
+
? { type: "axisRef", value: parsed.id as SingleAxisSelector }
|
|
16
|
+
: { type: "columnRef", value: parsed.id };
|
|
18
17
|
}
|
|
19
18
|
|
|
20
19
|
/** Converts a FilterSpec tree into a SpecQueryExpression. */
|
|
21
|
-
export function filterSpecToSpecQueryExpr(
|
|
22
|
-
filter: FilterSpec<
|
|
20
|
+
export function filterSpecToSpecQueryExpr<Leaf extends FilterSpecLeaf<string>>(
|
|
21
|
+
filter: FilterSpec<Leaf>,
|
|
23
22
|
): SpecQueryExpression {
|
|
24
23
|
return traverseFilterSpec(filter, {
|
|
25
24
|
leaf: leafToSpecQueryExpr,
|
|
@@ -39,7 +38,9 @@ export function filterSpecToSpecQueryExpr(
|
|
|
39
38
|
});
|
|
40
39
|
}
|
|
41
40
|
|
|
42
|
-
function leafToSpecQueryExpr
|
|
41
|
+
function leafToSpecQueryExpr<Leaf extends FilterSpecLeaf<string>>(
|
|
42
|
+
filter: Leaf,
|
|
43
|
+
): SpecQueryExpression {
|
|
43
44
|
switch (filter.type) {
|
|
44
45
|
case "patternEquals":
|
|
45
46
|
return {
|
package/src/filters/distill.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import { DistributiveKeys, UnionToTuples } from "@milaboratories/helpers";
|
|
2
|
-
import {
|
|
2
|
+
import {
|
|
3
|
+
RootFilterSpec,
|
|
4
|
+
type FilterSpec,
|
|
5
|
+
type FilterSpecLeaf,
|
|
6
|
+
} from "@milaboratories/pl-model-common";
|
|
3
7
|
import { traverseFilterSpec } from "./traverse";
|
|
8
|
+
import { InferFilterSpecLeaf } from "@milaboratories/pl-model-common";
|
|
4
9
|
|
|
5
10
|
/** All possible field names that can appear in any FilterSpecLeaf variant. */
|
|
6
11
|
type FilterSpecLeafKey = DistributiveKeys<FilterSpecLeaf<string>>;
|
|
@@ -41,23 +46,26 @@ function distillLeaf(node: Record<string, unknown>): FilterSpecLeaf<string> {
|
|
|
41
46
|
* Strips non-FilterSpec metadata (whitelist approach) and removes
|
|
42
47
|
* unfilled leaves (type is undefined or any required field is undefined).
|
|
43
48
|
*/
|
|
44
|
-
export function distillFilterSpec<
|
|
45
|
-
|
|
46
|
-
|
|
49
|
+
export function distillFilterSpec<
|
|
50
|
+
FS extends FilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>,
|
|
51
|
+
R extends FS extends RootFilterSpec<FilterSpecLeaf<unknown>, unknown, unknown>
|
|
52
|
+
? RootFilterSpec<InferFilterSpecLeaf<FS>>
|
|
53
|
+
: FilterSpec<InferFilterSpecLeaf<FS>>,
|
|
54
|
+
>(filter: null | undefined | FS): null | R {
|
|
47
55
|
if (filter == null) return null;
|
|
48
|
-
return traverseFilterSpec(filter, {
|
|
56
|
+
return traverseFilterSpec<FS, null | R>(filter, {
|
|
49
57
|
leaf: (leaf) => {
|
|
50
58
|
if (!isFilledLeaf(leaf as Record<string, unknown>)) return null;
|
|
51
|
-
return distillLeaf(leaf as Record<string, unknown>) as
|
|
59
|
+
return distillLeaf(leaf as Record<string, unknown>) as R;
|
|
52
60
|
},
|
|
53
61
|
and: (results) => {
|
|
54
|
-
const filtered = results.filter((f): f is
|
|
55
|
-
return filtered.length === 0 ? null : { type: "and", filters: filtered };
|
|
62
|
+
const filtered = results.filter((f): f is NonNullable<typeof f> => f !== null);
|
|
63
|
+
return filtered.length === 0 ? null : ({ type: "and", filters: filtered } as R);
|
|
56
64
|
},
|
|
57
65
|
or: (results) => {
|
|
58
|
-
const filtered = results.filter((f): f is
|
|
59
|
-
return filtered.length === 0 ? null : { type: "or", filters: filtered };
|
|
66
|
+
const filtered = results.filter((f): f is NonNullable<typeof f> => f !== null);
|
|
67
|
+
return filtered.length === 0 ? null : ({ type: "or", filters: filtered } as R);
|
|
60
68
|
},
|
|
61
|
-
not: (result) => (result === null ? null : { type: "not", filter: result }),
|
|
69
|
+
not: (result) => (result === null ? null : ({ type: "not", filter: result } as R)),
|
|
62
70
|
});
|
|
63
71
|
}
|