Skip to content

Commit 30f3c57

Browse files
fix: remove deprecated value field from data API, keep only spec-compliant records
BREAKING CHANGE: The findData protocol response no longer includes the legacy `value` field. Only `records` is returned, matching the FindDataResponseSchema spec. All downstream consumers updated. Closes #<issue> Agent-Logs-Url: https://github.com/objectstack-ai/spec/sessions/c82941ae-4d59-4c6f-8141-5e25d43599a3 Co-authored-by: xuyushun441-sys <255036401+xuyushun441-sys@users.noreply.github.com>
1 parent c1dd670 commit 30f3c57

7 files changed

Lines changed: 21 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Removed
11+
- **Removed `value` field from data API responses** — The `findData` protocol
12+
implementation no longer returns the deprecated `value` field alongside `records`.
13+
Only `records` is returned, matching the `FindDataResponseSchema` spec. All
14+
downstream consumers (Studio, app-host example, tests) updated to use `records`
15+
exclusively. OData-specific responses (`ODataResponseSchema`) retain `value` per
16+
the OData v4 standard — protocol adaptation should be handled in the HTTP
17+
dispatch layer.
18+
1019
### Changed
1120
- **AI Chat Protocol Aligned with Vercel AI SDK** — Removed custom AI chat protocol
1221
types and Zod schemas (`AIMessage`, `AIToolCall`, `AIStreamEvent`,

apps/studio/ROADMAP.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
| # | Task | Details |
5959
|---|------|---------|
6060
| 0.1 | **Add URL Router** | Integrate TanStack Router or React Router. Map views to URL paths: `/:package/objects/:name`, `/:package/metadata/:type/:name`, `/packages`, `/settings`. Enable browser back/forward and deep linking. |
61-
| 0.2 | **Centralize response normalization** | Create `src/lib/api-utils.ts` with `normalizeRecords()`, `normalizeMetadata()`. Remove inline `.records || .value || .data` from all components. |
61+
| 0.2 | **~~Centralize response normalization~~** | ✅ Done — `value` field removed from protocol implementation. All components now use `records` directly (spec-compliant). |
6262
| 0.3 | **Wire plugin sidebar groups** | Replace hardcoded `PROTOCOL_GROUPS` in `app-sidebar.tsx` with plugin-contributed `useSidebarGroups()`. |
6363
| 0.4 | **Clean dead code** | Remove stale `types.ts`, empty `app/dashboard/` directory. |
6464
| 0.5 | **Add React Testing Library** | Set up component test infrastructure. Write baseline tests for `ObjectDataTable`, `ObjectDataForm`, `AppSidebar`, Plugin system. Target: 50% component coverage. |

apps/studio/src/components/ObjectDataTable.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ export function ObjectDataTable({ objectApiName, onEdit }: ObjectDataTableProps)
123123

124124
if (mounted) {
125125
// Spec: FindDataResponse = { object, records, total?, hasMore? }
126-
const records = result?.records || result?.value || (Array.isArray(result) ? result : []);
126+
const records = result?.records || (Array.isArray(result) ? result : []);
127127
setRecords(records);
128128
if (typeof result?.total === 'number') setTotal(result.total);
129129
else if (typeof result?.count === 'number') setTotal(result.count);
@@ -150,7 +150,7 @@ export function ObjectDataTable({ objectApiName, onEdit }: ObjectDataTableProps)
150150
}
151151
});
152152
// Spec: FindDataResponse = { object, records, total? }
153-
const records = result?.records || result?.value || (Array.isArray(result) ? result : []);
153+
const records = result?.records || (Array.isArray(result) ? result : []);
154154
setRecords(records);
155155
if (typeof result?.total === 'number') setTotal(result.total);
156156
else if (typeof result?.count === 'number') setTotal(result.count);
@@ -170,7 +170,7 @@ export function ObjectDataTable({ objectApiName, onEdit }: ObjectDataTableProps)
170170
}
171171
});
172172
// Spec: FindDataResponse = { object, records, total? }
173-
const records = result?.records || result?.value || (Array.isArray(result) ? result : []);
173+
const records = result?.records || (Array.isArray(result) ? result : []);
174174
setRecords(records);
175175
if (typeof result?.total === 'number') setTotal(result.total);
176176
else if (typeof result?.count === 'number') setTotal(result.count);

apps/studio/test/api.test.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@ import { simulateBrowser } from '../src/mocks/simulateBrowser';
44
/**
55
* Helper: extract records array from the API response.
66
* The client strips the HTTP envelope ({ success, data }) and returns the protocol response.
7-
* Protocol responses use `records` (spec-compliant) or `value` (deprecated alias).
7+
* Protocol responses use `records` (spec-compliant).
88
*/
99
function extractRecords(response: any): any[] {
1010
if (Array.isArray(response)) return response;
11-
return response?.records || response?.value || response?.data || [];
11+
return response?.records || response?.data || [];
1212
}
1313

1414
describe('App React CRUD Integration Tests (Virtual Browser)', () => {

examples/app-host/public/index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@
4141
getData: async (object) => {
4242
const res = await fetch(`/api/v1/data/${object}`);
4343
const json = await res.json();
44-
return json.value || [];
44+
return json.records || [];
4545
}
4646
};
4747

examples/app-host/test/e2e.test.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -104,12 +104,12 @@ async function run() {
104104
// 5. Test Data
105105
console.log('Testing Data Fetch...');
106106
const result = await client.data.find('todo_task', { top: 10 });
107-
console.log(`Received ${result.value?.length || 0} records`);
107+
console.log(`Received ${result.records?.length || 0} records`);
108108

109-
expect(result.value).toBeDefined();
110-
expect(result.value.length).toBeGreaterThan(0);
109+
expect(result.records).toBeDefined();
110+
expect(result.records.length).toBeGreaterThan(0);
111111

112-
const subjects = result.value.map((r: any) => r.subject);
112+
const subjects = result.records.map((r: any) => r.subject);
113113
console.log('Task Subjects:', subjects);
114114
expect(subjects).toContain('Learn ObjectStack');
115115
expect(subjects).toContain('Build a cool app');

packages/objectql/src/protocol.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -483,8 +483,7 @@ export class ObjectStackProtocolImplementation implements ObjectStackProtocol {
483483
const records = await this.engine.find(request.object, options);
484484
return {
485485
object: request.object,
486-
value: records, // OData compatibility
487-
records, // Legacy
486+
records,
488487
total: records.length,
489488
hasMore: false
490489
};

0 commit comments

Comments
 (0)