Skip to content

Commit 08ec147

Browse files
committed
fix(rest): escape the NUL batch-dedup separator + regenerate batch docs reference
CI follow-up on the cross-object batch hardening (#1604): - The per-op (object, action) dedup key in the /batch handler used a raw NUL (0x00) byte as its separator, which trips the check:nul-bytes gate (a raw NUL makes the file read as binary to grep/ripgrep). Replaced with the standard unicode NUL escape sequence, matching the convention already used for the exec-ctx memo key elsewhere in rest-server.ts. Byte-identical at runtime. - Regenerated content/docs/references/api/batch.mdx (generated from the Zod spec) so it documents the new CrossObjectBatch* schemas — the check:docs gate requires the reference to track packages/spec. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_015DgfsaEfmwVAY1SsPtQJ6U
1 parent 775d552 commit 08ec147

2 files changed

Lines changed: 40 additions & 3 deletions

File tree

content/docs/references/api/batch.mdx

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@ Industry alignment: Salesforce Bulk API, Microsoft Dynamics Bulk Operations
3030
## TypeScript Usage
3131

3232
```typescript
33-
import { BatchConfig, BatchOperationResult, BatchOperationType, BatchOptions, BatchRecord, BatchUpdateRequest, BatchUpdateResponse, DeleteManyRequest, UpdateManyRequest } from '@objectstack/spec/api';
34-
import type { BatchConfig, BatchOperationResult, BatchOperationType, BatchOptions, BatchRecord, BatchUpdateRequest, BatchUpdateResponse, DeleteManyRequest, UpdateManyRequest } from '@objectstack/spec/api';
33+
import { BatchConfig, BatchOperationResult, BatchOperationType, BatchOptions, BatchRecord, BatchUpdateRequest, BatchUpdateResponse, CrossObjectBatchOperation, CrossObjectBatchRequest, CrossObjectBatchResponse, DeleteManyRequest, UpdateManyRequest } from '@objectstack/spec/api';
34+
import type { BatchConfig, BatchOperationResult, BatchOperationType, BatchOptions, BatchRecord, BatchUpdateRequest, BatchUpdateResponse, CrossObjectBatchOperation, CrossObjectBatchRequest, CrossObjectBatchResponse, DeleteManyRequest, UpdateManyRequest } from '@objectstack/spec/api';
3535

3636
// Validate data
3737
const result = BatchConfig.parse(data);
@@ -135,6 +135,43 @@ const result = BatchConfig.parse(data);
135135
| **results** | `{ id?: string; success: boolean; errors?: { code: string; message: string; category?: string; details?: any; … }[]; data?: Record<string, any>; … }[]` || Detailed results for each record |
136136

137137

138+
---
139+
140+
## CrossObjectBatchOperation
141+
142+
### Properties
143+
144+
| Property | Type | Required | Description |
145+
| :--- | :--- | :--- | :--- |
146+
| **object** | `string` || Target object (table) name |
147+
| **action** | `Enum<'create' \| 'update' \| 'delete'>` || Operation to perform (default: create) |
148+
| **id** | `string` | optional | Target record id — required for update and delete |
149+
| **data** | `Record<string, any>` | optional | Record payload for create/update; a value may be `{ $ref: <opIndex> }` to reference an earlier op's created id |
150+
151+
152+
---
153+
154+
## CrossObjectBatchRequest
155+
156+
### Properties
157+
158+
| Property | Type | Required | Description |
159+
| :--- | :--- | :--- | :--- |
160+
| **operations** | `{ object: string; action: Enum<'create' \| 'update' \| 'delete'>; id?: string; data?: Record<string, any> }[]` || Ordered operations executed in one transaction |
161+
| **atomic** | `boolean` || Always true — the cross-object batch is all-or-nothing |
162+
163+
164+
---
165+
166+
## CrossObjectBatchResponse
167+
168+
### Properties
169+
170+
| Property | Type | Required | Description |
171+
| :--- | :--- | :--- | :--- |
172+
| **results** | `any[]` || Per-operation result, index-aligned with the request operations |
173+
174+
138175
---
139176

140177
## DeleteManyRequest

packages/rest/src/rest-server.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6103,7 +6103,7 @@ export class RestServer {
61036103
const byName = new Map<string, any>(items.map((o: any) => [o?.name, o]));
61046104
const checked = new Set<string>();
61056105
for (const op of ops) {
6106-
const key = `${op.object}
6106+
const key = `${op.object}\u0000${op.action}`;
61076107
if (checked.has(key)) continue;
61086108
checked.add(key);
61096109
const obj = byName.get(op.object);

0 commit comments

Comments
 (0)