@object-ui/data-objectstack 6.0.4 → 6.1.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # @object-ui/data-objectstack
2
2
 
3
+ ## 6.1.0
4
+
5
+ ### Patch Changes
6
+
7
+ - Updated dependencies [991b62d]
8
+ - @object-ui/core@6.1.0
9
+ - @object-ui/types@6.1.0
10
+
3
11
  ## 6.0.4
4
12
 
5
13
  ### Patch Changes
package/dist/index.cjs CHANGED
@@ -586,15 +586,21 @@ function createObjectStackUserStateAdapter(options) {
586
586
  let cachedRowId = null;
587
587
  const findExisting = async () => {
588
588
  const params = {
589
- filter: {
589
+ $filter: {
590
590
  user_id: userId,
591
591
  key
592
592
  },
593
- limit: 1
593
+ $top: 1
594
594
  };
595
595
  const result = await dataSource.find(resource, params);
596
596
  const rows = result?.data ?? [];
597
- return rows.length > 0 ? rows[0] : null;
597
+ const match = rows.find((r) => {
598
+ if (!r) return false;
599
+ const userMismatch = r.user_id !== void 0 && r.user_id !== userId;
600
+ const keyMismatch = r.key !== void 0 && r.key !== key;
601
+ return !userMismatch && !keyMismatch;
602
+ });
603
+ return match ?? null;
598
604
  };
599
605
  const decodeValue = (value) => {
600
606
  if (Array.isArray(value)) return value;
package/dist/index.js CHANGED
@@ -539,15 +539,21 @@ function createObjectStackUserStateAdapter(options) {
539
539
  let cachedRowId = null;
540
540
  const findExisting = async () => {
541
541
  const params = {
542
- filter: {
542
+ $filter: {
543
543
  user_id: userId,
544
544
  key
545
545
  },
546
- limit: 1
546
+ $top: 1
547
547
  };
548
548
  const result = await dataSource.find(resource, params);
549
549
  const rows = result?.data ?? [];
550
- return rows.length > 0 ? rows[0] : null;
550
+ const match = rows.find((r) => {
551
+ if (!r) return false;
552
+ const userMismatch = r.user_id !== void 0 && r.user_id !== userId;
553
+ const keyMismatch = r.key !== void 0 && r.key !== key;
554
+ return !userMismatch && !keyMismatch;
555
+ });
556
+ return match ?? null;
551
557
  };
552
558
  const decodeValue = (value) => {
553
559
  if (Array.isArray(value)) return value;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@object-ui/data-objectstack",
3
- "version": "6.0.4",
3
+ "version": "6.1.0",
4
4
  "description": "ObjectStack Data Adapter for Object UI",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -23,13 +23,13 @@
23
23
  ],
24
24
  "dependencies": {
25
25
  "@objectstack/client": "^5.2.0",
26
- "@object-ui/core": "6.0.4",
27
- "@object-ui/types": "6.0.4"
26
+ "@object-ui/core": "6.1.0",
27
+ "@object-ui/types": "6.1.0"
28
28
  },
29
29
  "devDependencies": {
30
30
  "tsup": "^8.5.1",
31
31
  "typescript": "^6.0.3",
32
- "vitest": "^4.1.6"
32
+ "vitest": "^4.1.7"
33
33
  },
34
34
  "publishConfig": {
35
35
  "access": "public"
@@ -39,8 +39,8 @@ describe('createObjectStackUserStateAdapter', () => {
39
39
 
40
40
  expect(items).toEqual([]);
41
41
  expect(ds.find).toHaveBeenCalledWith('sys_user_preference', {
42
- filter: { user_id: 'u1', key: 'ui.favorites' },
43
- limit: 1,
42
+ $filter: { user_id: 'u1', key: 'ui.favorites' },
43
+ $top: 1,
44
44
  });
45
45
  });
46
46
 
package/src/userState.ts CHANGED
@@ -105,16 +105,31 @@ export function createObjectStackUserStateAdapter<T = unknown>(
105
105
  let cachedRowId: string | number | null = null;
106
106
 
107
107
  const findExisting = async (): Promise<UserPreferenceRecord | null> => {
108
+ // NOTE: `QueryParams` uses OData-style `$`-prefixed keys. Using the bare
109
+ // names (`filter`, `limit`) silently drops the predicate at the
110
+ // `convertQueryParams` layer, which then returns *any* row in the
111
+ // `sys_user_preference` table — that caused the Favorites adapter to load
112
+ // the Recents row (and vice-versa), so clicked items leaked into Starred.
108
113
  const params: QueryParams = {
109
- filter: {
114
+ $filter: {
110
115
  user_id: userId,
111
116
  key,
112
117
  },
113
- limit: 1,
118
+ $top: 1,
114
119
  };
115
120
  const result = await dataSource.find(resource, params);
116
121
  const rows = (result?.data ?? []) as UserPreferenceRecord[];
117
- return rows.length > 0 ? rows[0] : null;
122
+ // Defensive: if the backend ignored our predicate and returned mixed
123
+ // rows, only accept ones tagged for this (user, key) pair. Rows that
124
+ // omit those metadata fields entirely are trusted (covers mocks and
125
+ // backends that strip metadata from the projection).
126
+ const match = rows.find(r => {
127
+ if (!r) return false;
128
+ const userMismatch = r.user_id !== undefined && r.user_id !== userId;
129
+ const keyMismatch = r.key !== undefined && r.key !== key;
130
+ return !userMismatch && !keyMismatch;
131
+ });
132
+ return match ?? null;
118
133
  };
119
134
 
120
135
  const decodeValue = (value: unknown): T[] => {