@platforma-sdk/model 1.48.4 → 1.48.12
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/annotations/converter.cjs +5 -1
- package/dist/annotations/converter.cjs.map +1 -1
- package/dist/annotations/converter.d.ts.map +1 -1
- package/dist/annotations/converter.js +5 -1
- package/dist/annotations/converter.js.map +1 -1
- package/dist/package.json.cjs +1 -1
- package/dist/package.json.js +1 -1
- package/package.json +7 -7
- package/src/annotations/converter.test.ts +142 -5
- package/src/annotations/converter.ts +6 -1
|
@@ -14,7 +14,11 @@ function filterPredicate(item) {
|
|
|
14
14
|
if (item.type === 'and') {
|
|
15
15
|
return item.filters.length > 0;
|
|
16
16
|
}
|
|
17
|
-
|
|
17
|
+
if (item.type === 'not') {
|
|
18
|
+
return filterPredicate(item.filter);
|
|
19
|
+
}
|
|
20
|
+
// Filter out any item that has undefined values in required fields
|
|
21
|
+
return !Object.values(item).some((v) => v === undefined);
|
|
18
22
|
}
|
|
19
23
|
function filterEmptyPeaces(item) {
|
|
20
24
|
if (item.type === 'or' || item.type === 'and') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converter.cjs","sources":["../../src/annotations/converter.ts"],"sourcesContent":["import { when } from '@milaboratories/ptabler-expression-js';\nimport type { FilterSpec } from '../filters';\nimport { convertFilterUiToExpressionImpl } from '../filters/converter';\nimport type { ExpressionSpec, FilterSpecUi } from './types';\n\nfunction filterPredicate(item: FilterSpec): boolean {\n // No need to convert empty steps\n if (item.type == null) {\n return false;\n }\n\n if (item.type === 'or') {\n return item.filters.length > 0;\n }\n\n if (item.type === 'and') {\n return item.filters.length > 0;\n }\n\n return
|
|
1
|
+
{"version":3,"file":"converter.cjs","sources":["../../src/annotations/converter.ts"],"sourcesContent":["import { when } from '@milaboratories/ptabler-expression-js';\nimport type { FilterSpec } from '../filters';\nimport { convertFilterUiToExpressionImpl } from '../filters/converter';\nimport type { ExpressionSpec, FilterSpecUi } from './types';\n\nfunction filterPredicate(item: FilterSpec): boolean {\n // No need to convert empty steps\n if (item.type == null) {\n return false;\n }\n\n if (item.type === 'or') {\n return item.filters.length > 0;\n }\n\n if (item.type === 'and') {\n return item.filters.length > 0;\n }\n\n if (item.type === 'not') {\n return filterPredicate(item.filter);\n }\n\n // Filter out any item that has undefined values in required fields\n return !Object.values(item).some((v) => v === undefined);\n}\n\nfunction filterEmptyPeaces(item: FilterSpec): FilterSpec {\n if (item.type === 'or' || item.type === 'and') {\n const filtered = item.filters\n .map(filterEmptyPeaces)\n .filter(filterPredicate);\n return {\n ...item,\n filters: filtered,\n };\n }\n\n return item;\n}\n\nexport function convertFilterSpecsToExpressionSpecs(annotationsUI: FilterSpecUi[]): ExpressionSpec[] {\n const validAnnotationsUI = annotationsUI.map((step) => ({\n label: step.label,\n filter: filterEmptyPeaces(step.filter),\n }));\n return validAnnotationsUI\n .map((step): ExpressionSpec => ({\n type: 'alias',\n name: step.label.trim(),\n value: when(convertFilterUiToExpressionImpl(step.filter)).then(true).otherwise(false).toJSON(),\n }));\n}\n"],"names":["when","convertFilterUiToExpressionImpl"],"mappings":";;;;;AAKA,SAAS,eAAe,CAAC,IAAgB,EAAA;;AAEvC,IAAA,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE;AACrB,QAAA,OAAO,KAAK;IACd;AAEA,IAAA,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;AACtB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;IAChC;AAEA,IAAA,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE;AACvB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;IAChC;AAEA,IAAA,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE;AACvB,QAAA,OAAO,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;IACrC;;AAGA,IAAA,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;AAC1D;AAEA,SAAS,iBAAiB,CAAC,IAAgB,EAAA;AACzC,IAAA,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE;AAC7C,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC;aACnB,GAAG,CAAC,iBAAiB;aACrB,MAAM,CAAC,eAAe,CAAC;QAC1B,OAAO;AACL,YAAA,GAAG,IAAI;AACP,YAAA,OAAO,EAAE,QAAQ;SAClB;IACH;AAEA,IAAA,OAAO,IAAI;AACb;AAEM,SAAU,mCAAmC,CAAC,aAA6B,EAAA;IAC/E,MAAM,kBAAkB,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM;QACtD,KAAK,EAAE,IAAI,CAAC,KAAK;AACjB,QAAA,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;AACvC,KAAA,CAAC,CAAC;AACH,IAAA,OAAO;AACJ,SAAA,GAAG,CAAC,CAAC,IAAI,MAAsB;AAC9B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QACvB,KAAK,EAAEA,wBAAI,CAACC,yCAA+B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE;AAC/F,KAAA,CAAC,CAAC;AACP;;;;"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/annotations/converter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"converter.d.ts","sourceRoot":"","sources":["../../src/annotations/converter.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAsC5D,wBAAgB,mCAAmC,CAAC,aAAa,EAAE,YAAY,EAAE,GAAG,cAAc,EAAE,CAWnG"}
|
|
@@ -12,7 +12,11 @@ function filterPredicate(item) {
|
|
|
12
12
|
if (item.type === 'and') {
|
|
13
13
|
return item.filters.length > 0;
|
|
14
14
|
}
|
|
15
|
-
|
|
15
|
+
if (item.type === 'not') {
|
|
16
|
+
return filterPredicate(item.filter);
|
|
17
|
+
}
|
|
18
|
+
// Filter out any item that has undefined values in required fields
|
|
19
|
+
return !Object.values(item).some((v) => v === undefined);
|
|
16
20
|
}
|
|
17
21
|
function filterEmptyPeaces(item) {
|
|
18
22
|
if (item.type === 'or' || item.type === 'and') {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"converter.js","sources":["../../src/annotations/converter.ts"],"sourcesContent":["import { when } from '@milaboratories/ptabler-expression-js';\nimport type { FilterSpec } from '../filters';\nimport { convertFilterUiToExpressionImpl } from '../filters/converter';\nimport type { ExpressionSpec, FilterSpecUi } from './types';\n\nfunction filterPredicate(item: FilterSpec): boolean {\n // No need to convert empty steps\n if (item.type == null) {\n return false;\n }\n\n if (item.type === 'or') {\n return item.filters.length > 0;\n }\n\n if (item.type === 'and') {\n return item.filters.length > 0;\n }\n\n return
|
|
1
|
+
{"version":3,"file":"converter.js","sources":["../../src/annotations/converter.ts"],"sourcesContent":["import { when } from '@milaboratories/ptabler-expression-js';\nimport type { FilterSpec } from '../filters';\nimport { convertFilterUiToExpressionImpl } from '../filters/converter';\nimport type { ExpressionSpec, FilterSpecUi } from './types';\n\nfunction filterPredicate(item: FilterSpec): boolean {\n // No need to convert empty steps\n if (item.type == null) {\n return false;\n }\n\n if (item.type === 'or') {\n return item.filters.length > 0;\n }\n\n if (item.type === 'and') {\n return item.filters.length > 0;\n }\n\n if (item.type === 'not') {\n return filterPredicate(item.filter);\n }\n\n // Filter out any item that has undefined values in required fields\n return !Object.values(item).some((v) => v === undefined);\n}\n\nfunction filterEmptyPeaces(item: FilterSpec): FilterSpec {\n if (item.type === 'or' || item.type === 'and') {\n const filtered = item.filters\n .map(filterEmptyPeaces)\n .filter(filterPredicate);\n return {\n ...item,\n filters: filtered,\n };\n }\n\n return item;\n}\n\nexport function convertFilterSpecsToExpressionSpecs(annotationsUI: FilterSpecUi[]): ExpressionSpec[] {\n const validAnnotationsUI = annotationsUI.map((step) => ({\n label: step.label,\n filter: filterEmptyPeaces(step.filter),\n }));\n return validAnnotationsUI\n .map((step): ExpressionSpec => ({\n type: 'alias',\n name: step.label.trim(),\n value: when(convertFilterUiToExpressionImpl(step.filter)).then(true).otherwise(false).toJSON(),\n }));\n}\n"],"names":[],"mappings":";;;AAKA,SAAS,eAAe,CAAC,IAAgB,EAAA;;AAEvC,IAAA,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,EAAE;AACrB,QAAA,OAAO,KAAK;IACd;AAEA,IAAA,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,EAAE;AACtB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;IAChC;AAEA,IAAA,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE;AACvB,QAAA,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC;IAChC;AAEA,IAAA,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE;AACvB,QAAA,OAAO,eAAe,CAAC,IAAI,CAAC,MAAM,CAAC;IACrC;;AAGA,IAAA,OAAO,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,SAAS,CAAC;AAC1D;AAEA,SAAS,iBAAiB,CAAC,IAAgB,EAAA;AACzC,IAAA,IAAI,IAAI,CAAC,IAAI,KAAK,IAAI,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,EAAE;AAC7C,QAAA,MAAM,QAAQ,GAAG,IAAI,CAAC;aACnB,GAAG,CAAC,iBAAiB;aACrB,MAAM,CAAC,eAAe,CAAC;QAC1B,OAAO;AACL,YAAA,GAAG,IAAI;AACP,YAAA,OAAO,EAAE,QAAQ;SAClB;IACH;AAEA,IAAA,OAAO,IAAI;AACb;AAEM,SAAU,mCAAmC,CAAC,aAA6B,EAAA;IAC/E,MAAM,kBAAkB,GAAG,aAAa,CAAC,GAAG,CAAC,CAAC,IAAI,MAAM;QACtD,KAAK,EAAE,IAAI,CAAC,KAAK;AACjB,QAAA,MAAM,EAAE,iBAAiB,CAAC,IAAI,CAAC,MAAM,CAAC;AACvC,KAAA,CAAC,CAAC;AACH,IAAA,OAAO;AACJ,SAAA,GAAG,CAAC,CAAC,IAAI,MAAsB;AAC9B,QAAA,IAAI,EAAE,OAAO;AACb,QAAA,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,EAAE;QACvB,KAAK,EAAE,IAAI,CAAC,+BAA+B,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,MAAM,EAAE;AAC/F,KAAA,CAAC,CAAC;AACP;;;;"}
|
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.48.
|
|
3
|
+
"version": "1.48.12",
|
|
4
4
|
"description": "Platforma.bio SDK / Block Model",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/index.d.ts",
|
|
@@ -23,19 +23,19 @@
|
|
|
23
23
|
"canonicalize": "~2.1.0",
|
|
24
24
|
"es-toolkit": "^1.39.10",
|
|
25
25
|
"zod": "~3.23.8",
|
|
26
|
-
"@milaboratories/ptabler-expression-js": "1.1.7",
|
|
27
26
|
"@milaboratories/pl-model-common": "1.21.10",
|
|
28
|
-
"@milaboratories/pl-error-like": "1.12.5"
|
|
27
|
+
"@milaboratories/pl-error-like": "1.12.5",
|
|
28
|
+
"@milaboratories/ptabler-expression-js": "1.1.7"
|
|
29
29
|
},
|
|
30
30
|
"devDependencies": {
|
|
31
31
|
"typescript": "~5.6.3",
|
|
32
32
|
"vitest": "^4.0.7",
|
|
33
33
|
"fast-json-patch": "^3.1.1",
|
|
34
|
-
"@milaboratories/build-configs": "1.2.
|
|
34
|
+
"@milaboratories/build-configs": "1.2.1",
|
|
35
35
|
"@platforma-sdk/eslint-config": "1.2.0",
|
|
36
|
-
"@milaboratories/
|
|
37
|
-
"@milaboratories/
|
|
38
|
-
"@milaboratories/ts-
|
|
36
|
+
"@milaboratories/ts-configs": "1.2.0",
|
|
37
|
+
"@milaboratories/helpers": "1.12.1",
|
|
38
|
+
"@milaboratories/ts-builder": "1.2.1"
|
|
39
39
|
},
|
|
40
40
|
"scripts": {
|
|
41
41
|
"type-check": "ts-builder types --target node",
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import type { SUniversalPColumnId } from '@milaboratories/pl-model-common';
|
|
2
1
|
import { describe, expect, test } from 'vitest';
|
|
3
2
|
import { convertFilterSpecsToExpressionSpecs } from './converter';
|
|
4
3
|
import { FilterSpecUi } from './types';
|
|
@@ -16,8 +15,8 @@ describe('convertFilterSpecsToExpressionSpecs', () => {
|
|
|
16
15
|
filter: {
|
|
17
16
|
type: 'and',
|
|
18
17
|
filters: [
|
|
19
|
-
{ type: 'isNA', column: 'colA'
|
|
20
|
-
{ type: 'patternEquals', column: 'colB'
|
|
18
|
+
{ type: 'isNA', column: 'colA' } as any,
|
|
19
|
+
{ type: 'patternEquals', column: 'colB', value: 'abc' } as any,
|
|
21
20
|
],
|
|
22
21
|
},
|
|
23
22
|
},
|
|
@@ -69,6 +68,144 @@ describe('convertFilterSpecsToExpressionSpecs', () => {
|
|
|
69
68
|
const script = convertFilterSpecsToExpressionSpecs(filters);
|
|
70
69
|
expect(script).toEqual(expected);
|
|
71
70
|
});
|
|
72
|
-
});
|
|
73
|
-
|
|
74
71
|
|
|
72
|
+
test('should filter out empty/unset filter conditions', () => {
|
|
73
|
+
const filters: FilterSpecUi[] = [
|
|
74
|
+
{
|
|
75
|
+
label: 'Step with various unset filters',
|
|
76
|
+
filter: {
|
|
77
|
+
type: 'and',
|
|
78
|
+
filters: [
|
|
79
|
+
{} as any,
|
|
80
|
+
{ type: undefined } as any,
|
|
81
|
+
{ type: 'isNA', column: 'colA' },
|
|
82
|
+
{ type: 'isNA', column: undefined } as any,
|
|
83
|
+
{ type: 'isNotNA', column: undefined } as any,
|
|
84
|
+
{ type: 'patternEquals', column: undefined, value: 'test' },
|
|
85
|
+
{ type: 'patternEquals', column: 'colX', value: undefined } as any,
|
|
86
|
+
{ type: 'patternNotEquals', column: undefined, value: 'test' } as any,
|
|
87
|
+
{ type: 'patternNotEquals', column: 'colX', value: undefined } as any,
|
|
88
|
+
{ type: 'patternContainSubsequence', column: undefined, value: 'test' } as any,
|
|
89
|
+
{ type: 'patternContainSubsequence', column: 'colX', value: undefined } as any,
|
|
90
|
+
{ type: 'equal', column: undefined, x: 5 } as any,
|
|
91
|
+
{ type: 'equal', column: 'colX', x: undefined } as any,
|
|
92
|
+
{ type: 'lessThan', column: undefined, x: 5 } as any,
|
|
93
|
+
{ type: 'lessThan', column: 'colX', x: undefined } as any,
|
|
94
|
+
{ type: 'greaterThan', column: undefined, x: 5 } as any,
|
|
95
|
+
{ type: 'greaterThan', column: 'colX', x: undefined } as any,
|
|
96
|
+
{ type: 'topN', column: undefined, n: 5 } as any,
|
|
97
|
+
{ type: 'topN', column: 'colX', n: undefined } as any,
|
|
98
|
+
{ type: 'bottomN', column: undefined, n: 5 } as any,
|
|
99
|
+
{ type: 'bottomN', column: 'colX', n: undefined } as any,
|
|
100
|
+
{ type: 'equalToColumn', column: undefined, rhs: 'colY' } as any,
|
|
101
|
+
{ type: 'equalToColumn', column: 'colX', rhs: undefined } as any,
|
|
102
|
+
{ type: 'greaterThanColumn', column: undefined, rhs: 'colY' } as any,
|
|
103
|
+
{ type: 'greaterThanColumn', column: 'colX', rhs: undefined } as any,
|
|
104
|
+
{ type: 'lessThanColumn', column: undefined, rhs: 'colY' } as any,
|
|
105
|
+
{ type: 'lessThanColumn', column: 'colX', rhs: undefined } as any,
|
|
106
|
+
{ type: undefined, column: 'colX', value: 'someValue' } as any,
|
|
107
|
+
],
|
|
108
|
+
},
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
label: 'Step with nested unset filters',
|
|
112
|
+
filter: {
|
|
113
|
+
type: 'or',
|
|
114
|
+
filters: [
|
|
115
|
+
{
|
|
116
|
+
type: 'and',
|
|
117
|
+
filters: [
|
|
118
|
+
{ type: undefined } as any,
|
|
119
|
+
{ type: 'patternEquals', column: 'colB', value: 'test' },
|
|
120
|
+
{ type: undefined, column: undefined } as any,
|
|
121
|
+
],
|
|
122
|
+
},
|
|
123
|
+
{ type: undefined } as any,
|
|
124
|
+
{
|
|
125
|
+
type: 'or',
|
|
126
|
+
filters: [
|
|
127
|
+
{ type: undefined } as any,
|
|
128
|
+
{ type: undefined, value: undefined } as any,
|
|
129
|
+
],
|
|
130
|
+
} as any,
|
|
131
|
+
],
|
|
132
|
+
},
|
|
133
|
+
},
|
|
134
|
+
];
|
|
135
|
+
const expected = [
|
|
136
|
+
{
|
|
137
|
+
name: 'Step with various unset filters',
|
|
138
|
+
type: 'alias',
|
|
139
|
+
value: {
|
|
140
|
+
conditions: [
|
|
141
|
+
{
|
|
142
|
+
then: {
|
|
143
|
+
type: 'const',
|
|
144
|
+
value: true,
|
|
145
|
+
},
|
|
146
|
+
when: {
|
|
147
|
+
type: 'and',
|
|
148
|
+
operands: [
|
|
149
|
+
{
|
|
150
|
+
type: 'is_na',
|
|
151
|
+
value: {
|
|
152
|
+
name: 'colA',
|
|
153
|
+
type: 'col',
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
},
|
|
158
|
+
},
|
|
159
|
+
],
|
|
160
|
+
otherwise: {
|
|
161
|
+
type: 'const',
|
|
162
|
+
value: false,
|
|
163
|
+
},
|
|
164
|
+
type: 'when_then_otherwise',
|
|
165
|
+
},
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: 'Step with nested unset filters',
|
|
169
|
+
type: 'alias',
|
|
170
|
+
value: {
|
|
171
|
+
conditions: [
|
|
172
|
+
{
|
|
173
|
+
then: {
|
|
174
|
+
type: 'const',
|
|
175
|
+
value: true,
|
|
176
|
+
},
|
|
177
|
+
when: {
|
|
178
|
+
type: 'or',
|
|
179
|
+
operands: [
|
|
180
|
+
{
|
|
181
|
+
type: 'and',
|
|
182
|
+
operands: [
|
|
183
|
+
{
|
|
184
|
+
lhs: {
|
|
185
|
+
name: 'colB',
|
|
186
|
+
type: 'col',
|
|
187
|
+
},
|
|
188
|
+
rhs: {
|
|
189
|
+
type: 'const',
|
|
190
|
+
value: 'test',
|
|
191
|
+
},
|
|
192
|
+
type: 'eq',
|
|
193
|
+
},
|
|
194
|
+
],
|
|
195
|
+
},
|
|
196
|
+
],
|
|
197
|
+
},
|
|
198
|
+
},
|
|
199
|
+
],
|
|
200
|
+
otherwise: {
|
|
201
|
+
type: 'const',
|
|
202
|
+
value: false,
|
|
203
|
+
},
|
|
204
|
+
type: 'when_then_otherwise',
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
];
|
|
208
|
+
const script = convertFilterSpecsToExpressionSpecs(filters);
|
|
209
|
+
expect(script).toEqual(expected);
|
|
210
|
+
});
|
|
211
|
+
});
|
|
@@ -17,7 +17,12 @@ function filterPredicate(item: FilterSpec): boolean {
|
|
|
17
17
|
return item.filters.length > 0;
|
|
18
18
|
}
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
if (item.type === 'not') {
|
|
21
|
+
return filterPredicate(item.filter);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
// Filter out any item that has undefined values in required fields
|
|
25
|
+
return !Object.values(item).some((v) => v === undefined);
|
|
21
26
|
}
|
|
22
27
|
|
|
23
28
|
function filterEmptyPeaces(item: FilterSpec): FilterSpec {
|