Skip to content

Commit 444c0ef

Browse files
authored
Merge pull request #1037 from objectstack-ai/copilot/remove-value-field-from-data-api
2 parents 2f44d3e + c12f088 commit 444c0ef

7 files changed

Lines changed: 23 additions & 13 deletions

File tree

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2727
reports listing every declared endpoint and its implementation status.
2828
- `ai` v6 as a dependency of `@objectstack/spec` for type re-exports
2929

30+
### Removed
31+
- **Removed `value` field from data API responses** — The `findData` protocol
32+
implementation no longer returns the deprecated `value` field alongside `records`.
33+
Only `records` is returned, matching the `FindDataResponseSchema` spec. All
34+
downstream consumers (Studio, app-host example, tests) updated to use `records`
35+
exclusively. OData-specific responses (`ODataResponseSchema`) retain `value` per
36+
the OData v4 standard — protocol-to-OData adaptation is handled in the HTTP
37+
dispatch layer.
38+
3039
### Changed
3140
- **AI Chat Protocol Aligned with Vercel AI SDK** — Removed custom AI chat protocol
3241
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: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -481,10 +481,11 @@ export class ObjectStackProtocolImplementation implements ObjectStackProtocol {
481481
}
482482

483483
const records = await this.engine.find(request.object, options);
484+
// Spec: FindDataResponseSchema — only `records` is returned.
485+
// OData `value` adaptation (if needed) is handled in the HTTP dispatch layer.
484486
return {
485487
object: request.object,
486-
value: records, // OData compatibility
487-
records, // Legacy
488+
records,
488489
total: records.length,
489490
hasMore: false
490491
};

0 commit comments

Comments
 (0)