@object-ui/data-objectstack 3.4.0 → 4.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,20 @@
1
1
  # @object-ui/data-objectstack
2
2
 
3
+ ## 4.0.1
4
+
5
+ ### Patch Changes
6
+
7
+ - @object-ui/types@4.0.1
8
+ - @object-ui/core@4.0.1
9
+
10
+ ## 4.0.0
11
+
12
+ ### Patch Changes
13
+
14
+ - Updated dependencies
15
+ - @object-ui/types@4.0.0
16
+ - @object-ui/core@4.0.0
17
+
3
18
  ## 3.4.0
4
19
 
5
20
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -829,6 +829,57 @@ function calculateAutoLayout(items, canvasWidth, padding = 40, gap = 40) {
829
829
  }
830
830
 
831
831
  // src/index.ts
832
+ var FILTER_OPERATOR_ALIASES = {
833
+ equals: "=",
834
+ eq: "=",
835
+ "==": "=",
836
+ not_equals: "!=",
837
+ notequals: "!=",
838
+ ne: "!=",
839
+ greater_than: ">",
840
+ greaterthan: ">",
841
+ gt: ">",
842
+ greater_than_or_equal: ">=",
843
+ greater_than_or_equals: ">=",
844
+ greaterthanorequal: ">=",
845
+ gte: ">=",
846
+ less_than: "<",
847
+ lessthan: "<",
848
+ lt: "<",
849
+ less_than_or_equal: "<=",
850
+ less_than_or_equals: "<=",
851
+ lessthanorequal: "<=",
852
+ lte: "<=",
853
+ in: "in",
854
+ not_in: "nin",
855
+ notin: "nin",
856
+ nin: "nin",
857
+ contains: "contains",
858
+ not_contains: "notcontains",
859
+ notcontains: "notcontains",
860
+ starts_with: "startswith",
861
+ startswith: "startswith",
862
+ ends_with: "endswith",
863
+ endswith: "endswith",
864
+ between: "between",
865
+ is_null: "isnull",
866
+ isnull: "isnull",
867
+ is_not_null: "isnotnull",
868
+ isnotnull: "isnotnull"
869
+ };
870
+ function normalizeFilterOperator(op) {
871
+ if (typeof op !== "string") return null;
872
+ const lower = op.toLowerCase();
873
+ return FILTER_OPERATOR_ALIASES[lower] ?? FILTER_OPERATOR_ALIASES[op] ?? op;
874
+ }
875
+ function objectFilterEntryToAST(entry) {
876
+ if (!entry || typeof entry !== "object") return null;
877
+ const field = entry.field ?? entry.name;
878
+ const rawOp = entry.operator ?? entry.op ?? "=";
879
+ const op = normalizeFilterOperator(rawOp);
880
+ if (!field || !op) return null;
881
+ return [String(field), op, entry.value];
882
+ }
832
883
  var discoveryCache = /* @__PURE__ */ new Map();
833
884
  async function getSharedDiscovery(baseUrl, fetcher) {
834
885
  const key = baseUrl || "<default>";
@@ -1322,7 +1373,18 @@ var ObjectStackAdapter = class {
1322
1373
  const isEmpty = Array.isArray(params.$filter) ? params.$filter.length === 0 : typeof params.$filter === "object" && Object.keys(params.$filter).length === 0;
1323
1374
  if (!isEmpty) {
1324
1375
  if (Array.isArray(params.$filter)) {
1325
- options.filters = params.$filter;
1376
+ const isObjectForm = params.$filter.length > 0 && typeof params.$filter[0] === "object" && !Array.isArray(params.$filter[0]) && params.$filter[0].field !== void 0;
1377
+ if (isObjectForm) {
1378
+ const tuples = params.$filter.map((entry) => objectFilterEntryToAST(entry)).filter((t) => t !== null);
1379
+ if (tuples.length === 0) {
1380
+ } else if (tuples.length === 1) {
1381
+ options.filters = tuples[0];
1382
+ } else {
1383
+ options.filters = ["and", ...tuples];
1384
+ }
1385
+ } else {
1386
+ options.filters = params.$filter;
1387
+ }
1326
1388
  } else {
1327
1389
  options.filters = convertFiltersToAST(params.$filter);
1328
1390
  }
package/dist/index.js CHANGED
@@ -787,6 +787,57 @@ function calculateAutoLayout(items, canvasWidth, padding = 40, gap = 40) {
787
787
  }
788
788
 
789
789
  // src/index.ts
790
+ var FILTER_OPERATOR_ALIASES = {
791
+ equals: "=",
792
+ eq: "=",
793
+ "==": "=",
794
+ not_equals: "!=",
795
+ notequals: "!=",
796
+ ne: "!=",
797
+ greater_than: ">",
798
+ greaterthan: ">",
799
+ gt: ">",
800
+ greater_than_or_equal: ">=",
801
+ greater_than_or_equals: ">=",
802
+ greaterthanorequal: ">=",
803
+ gte: ">=",
804
+ less_than: "<",
805
+ lessthan: "<",
806
+ lt: "<",
807
+ less_than_or_equal: "<=",
808
+ less_than_or_equals: "<=",
809
+ lessthanorequal: "<=",
810
+ lte: "<=",
811
+ in: "in",
812
+ not_in: "nin",
813
+ notin: "nin",
814
+ nin: "nin",
815
+ contains: "contains",
816
+ not_contains: "notcontains",
817
+ notcontains: "notcontains",
818
+ starts_with: "startswith",
819
+ startswith: "startswith",
820
+ ends_with: "endswith",
821
+ endswith: "endswith",
822
+ between: "between",
823
+ is_null: "isnull",
824
+ isnull: "isnull",
825
+ is_not_null: "isnotnull",
826
+ isnotnull: "isnotnull"
827
+ };
828
+ function normalizeFilterOperator(op) {
829
+ if (typeof op !== "string") return null;
830
+ const lower = op.toLowerCase();
831
+ return FILTER_OPERATOR_ALIASES[lower] ?? FILTER_OPERATOR_ALIASES[op] ?? op;
832
+ }
833
+ function objectFilterEntryToAST(entry) {
834
+ if (!entry || typeof entry !== "object") return null;
835
+ const field = entry.field ?? entry.name;
836
+ const rawOp = entry.operator ?? entry.op ?? "=";
837
+ const op = normalizeFilterOperator(rawOp);
838
+ if (!field || !op) return null;
839
+ return [String(field), op, entry.value];
840
+ }
790
841
  var discoveryCache = /* @__PURE__ */ new Map();
791
842
  async function getSharedDiscovery(baseUrl, fetcher) {
792
843
  const key = baseUrl || "<default>";
@@ -1280,7 +1331,18 @@ var ObjectStackAdapter = class {
1280
1331
  const isEmpty = Array.isArray(params.$filter) ? params.$filter.length === 0 : typeof params.$filter === "object" && Object.keys(params.$filter).length === 0;
1281
1332
  if (!isEmpty) {
1282
1333
  if (Array.isArray(params.$filter)) {
1283
- options.filters = params.$filter;
1334
+ const isObjectForm = params.$filter.length > 0 && typeof params.$filter[0] === "object" && !Array.isArray(params.$filter[0]) && params.$filter[0].field !== void 0;
1335
+ if (isObjectForm) {
1336
+ const tuples = params.$filter.map((entry) => objectFilterEntryToAST(entry)).filter((t) => t !== null);
1337
+ if (tuples.length === 0) {
1338
+ } else if (tuples.length === 1) {
1339
+ options.filters = tuples[0];
1340
+ } else {
1341
+ options.filters = ["and", ...tuples];
1342
+ }
1343
+ } else {
1344
+ options.filters = params.$filter;
1345
+ }
1284
1346
  } else {
1285
1347
  options.filters = convertFiltersToAST(params.$filter);
1286
1348
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/data-objectstack",
3
- "version": "3.4.0",
3
+ "version": "4.0.1",
4
4
  "description": "ObjectStack Data Adapter for Object UI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,8 +23,8 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "@objectstack/client": "^4.0.4",
26
- "@object-ui/core": "3.4.0",
27
- "@object-ui/types": "3.4.0"
26
+ "@object-ui/core": "4.0.1",
27
+ "@object-ui/types": "4.0.1"
28
28
  },
29
29
  "devDependencies": {
30
30
  "tsup": "^8.5.1",
package/src/index.ts CHANGED
@@ -18,6 +18,66 @@ import {
18
18
  createErrorFromResponse,
19
19
  } from './errors';
20
20
 
21
+ /**
22
+ * Map human-readable filter operator names produced by SDUI view configs
23
+ * (e.g. `lead.view.ts`) to the canonical operator symbols expected by the
24
+ * ObjectStack server's filter AST. Unknown operators fall through unchanged
25
+ * so existing AST-style entries keep working.
26
+ */
27
+ const FILTER_OPERATOR_ALIASES: Record<string, string> = {
28
+ equals: '=',
29
+ eq: '=',
30
+ '==': '=',
31
+ not_equals: '!=',
32
+ notequals: '!=',
33
+ ne: '!=',
34
+ greater_than: '>',
35
+ greaterthan: '>',
36
+ gt: '>',
37
+ greater_than_or_equal: '>=',
38
+ greater_than_or_equals: '>=',
39
+ greaterthanorequal: '>=',
40
+ gte: '>=',
41
+ less_than: '<',
42
+ lessthan: '<',
43
+ lt: '<',
44
+ less_than_or_equal: '<=',
45
+ less_than_or_equals: '<=',
46
+ lessthanorequal: '<=',
47
+ lte: '<=',
48
+ in: 'in',
49
+ not_in: 'nin',
50
+ notin: 'nin',
51
+ nin: 'nin',
52
+ contains: 'contains',
53
+ not_contains: 'notcontains',
54
+ notcontains: 'notcontains',
55
+ starts_with: 'startswith',
56
+ startswith: 'startswith',
57
+ ends_with: 'endswith',
58
+ endswith: 'endswith',
59
+ between: 'between',
60
+ is_null: 'isnull',
61
+ isnull: 'isnull',
62
+ is_not_null: 'isnotnull',
63
+ isnotnull: 'isnotnull',
64
+ };
65
+
66
+ function normalizeFilterOperator(op: unknown): string | null {
67
+ if (typeof op !== 'string') return null;
68
+ const lower = op.toLowerCase();
69
+ return FILTER_OPERATOR_ALIASES[lower] ?? FILTER_OPERATOR_ALIASES[op] ?? op;
70
+ }
71
+
72
+ function objectFilterEntryToAST(entry: any): [string, string, any] | null {
73
+ if (!entry || typeof entry !== 'object') return null;
74
+ const field = entry.field ?? entry.name;
75
+ const rawOp = entry.operator ?? entry.op ?? '=';
76
+ const op = normalizeFilterOperator(rawOp);
77
+ if (!field || !op) return null;
78
+ return [String(field), op, entry.value];
79
+ }
80
+
21
81
  // Module-level discovery cache. Multiple ObjectStackAdapter instances pointed
22
82
  // at the same baseUrl (e.g. ConditionalAuthWrapper's throwaway adapter +
23
83
  // AdapterProvider's main adapter) would otherwise each fire `/discovery`. By
@@ -749,8 +809,33 @@ export class ObjectStackAdapter<T = unknown> implements DataSource<T> {
749
809
  : typeof params.$filter === 'object' && Object.keys(params.$filter).length === 0;
750
810
  if (!isEmpty) {
751
811
  if (Array.isArray(params.$filter)) {
752
- // Assume active AST format if it's already an array
753
- options.filters = params.$filter;
812
+ // Two array shapes are accepted from upstream:
813
+ // 1. AST tuples: [field, op, value] — pass through.
814
+ // 2. Object form: [{ field, operator, value }, ...] — server-driven
815
+ // view configs (lead.view.ts etc.) use this. Translate each
816
+ // entry into the AST tuple shape and map human-readable
817
+ // operator names (`greater_than_or_equal`, `in`, `contains`,
818
+ // …) to the canonical symbols the server understands.
819
+ const isObjectForm = params.$filter.length > 0
820
+ && typeof params.$filter[0] === 'object'
821
+ && !Array.isArray(params.$filter[0])
822
+ && (params.$filter[0] as any).field !== undefined;
823
+ if (isObjectForm) {
824
+ const tuples = (params.$filter as any[])
825
+ .map(entry => objectFilterEntryToAST(entry))
826
+ .filter((t): t is [string, string, any] => t !== null);
827
+ if (tuples.length === 0) {
828
+ // All entries were unrecognized — drop the filter rather than
829
+ // sending a malformed array.
830
+ } else if (tuples.length === 1) {
831
+ options.filters = tuples[0];
832
+ } else {
833
+ options.filters = ['and', ...tuples];
834
+ }
835
+ } else {
836
+ // Already in AST format
837
+ options.filters = params.$filter;
838
+ }
754
839
  } else {
755
840
  options.filters = convertFiltersToAST(params.$filter);
756
841
  }